Clojure’s REPL, lein, pomegranate and classpath

Clojure iconWhile developing a more advanced Clojure project – one that uses many dependencies – it’s inevitable to run into jar management nightmare (aka “jar hell”). Leiningen helps a lot and it’s when it shines – you define the dependencies upfront and they’re available for the project, esp. when executing Clojure REPL with lein repl.

There’s however a situation where Leiningen won’t work – when you’re in Clojure REPL and need to add additional libraries with their (transitive) dependencies.

That’s where you may need pomegranate. Pomegranate “uses Aether to add a Maven artifact (and all of its transitive dependencies) to your Clojure runtime’s classpath dynamically.”

With Clojure, leiningen and pomegranate evaluating new APIs is so much smoother.

Give yourself a couple of minutes to give it a try.

  1. Create a project with lein new pomegranate-playground.
  2. Add [com.cemerick/pomegranate “0.0.10”] to the dependencies section of the project.clj.
  3. Run lein repl.
  4. While in Clojure’s REPL, execute (use ‘[cemerick.pomegranate :only (add-dependencies)]).
  5. Use (add-dependencies) to…add jars and their transitive dependencies to REPL’s classpath dynamically.
jacek:~/sandbox
$ lein new pomegranate-playground
Created new project in: /Users/jacek/sandbox/pomegranate-playground
Look over project.clj and start coding in pomegranate_playground/core.clj
jacek:~/sandbox
$ cd pomegranate-playground
jacek:~/sandbox/pomegranate-playground
$ lein version
Leiningen 1.7.1 on Java 1.7.0-jdk7u4-b17 OpenJDK 64-Bit Server VM
jacek:~/sandbox/pomegranate-playground
$ cat project.clj
(defproject pomegranate-playground "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [com.cemerick/pomegranate "0.0.10"]])
jacek:~/sandbox/pomegranate-playground
$ lein repl
REPL started; server listening on localhost port 56529
user=> (clojure-version)
"1.3.0"
user=> (use '[cemerick.pomegranate :only (add-dependencies)])
nil
user=> (add-dependencies :coordinates '
[[compojure "1.0.1"]])
{[javax.servlet/servlet-api "2.5"] nil, [clout "1.0.1"] nil, [org.clojure/core.incubator "0.1.0"] nil, [ring/ring-core "1.0.1"] #{[javax.servlet/servlet-api "2.5"] [commons-io "1.4"] [commons-codec "1.4"] [commons-fileupload "1.2.1"]}, [org.clojure/tools.macro "0.1.0"] nil, [commons-io "1.4"] nil, [compojure "1.0.1"] #{[clout "1.0.1"] [org.clojure/core.incubator "0.1.0"] [ring/ring-core "1.0.1"] [org.clojure/tools.macro "0.1.0"] [org.clojure/clojure "1.2.1"]}, [org.clojure/clojure "1.2.1"] nil, [commons-codec "1.4"] nil, [commons-fileupload "1.2.1"] nil}
user=> (use '[compojure.core :only (defroutes)])
nil
user=> (defroutes app)
#'
user/app

Thanks Chas!

Be Sociable, Share!
This entry was posted in Languages.

6 Responses to Clojure’s REPL, lein, pomegranate and classpath

  1. Thank you. This is perfect timing. I’ve got a Clojure project with three dependent libraries.

  2. j1n3l0 says:

    and if you use leiningen v2 you can skip steps 1 and 2 :)

    • I read your blog post twice or even more to have finally figured out how lein2 could do it without the steps 1 and 2 until I paid more attention and found the sentence: “Leiningen 2 has move its dependency management core to a new library, called pomegranate.” I believe it should be put in bold so it springs to mind at the moment eyes reach it. I even thought lein2 builds CLASSPATH with the jars from the local m2 repo – ALL jars (!) Thanks j1n3l0!

      BTW, what plugin do you use for code snippets in your blog? They’re astoundingly beautiful and readable!

  3. Pingback: Clojure easier? s/lein/lein2 – pomegranate is there already | Japila :: verba docent, exempla trahunt

Leave a Reply

%d bloggers like this: