While 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.
- Create a project with lein new pomegranate-playground.
- Add [com.cemerick/pomegranate "0.0.10"] to the dependencies section of the project.clj.
- Run lein repl.
- While in Clojure’s REPL, execute (use ‘[cemerick.pomegranate :only (add-dependencies)]).
- Use (add-dependencies) to…add jars and their transitive dependencies to REPL’s classpath dynamically.
$ 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!

Thank you. This is perfect timing. I’ve got a Clojure project with three dependent libraries.
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!
It’s my blog :) The wordpress plugin is called codecolorer.
When I saw pomegranate first time, I was thinking about writing a leiningen plugin to wrap it. So that I can skip step 1 and 2. I failed because pomegranate requires clojure 1.3 while lein1 only provides 1.2. The code is here: https://gist.github.com/1522789
codecolorer’s now part of the blog. Thanks twofold – once for lein2 and twice for the plugin.
Pingback: Clojure easier? s/lein/lein2 – pomegranate is there already | Japila :: verba docent, exempla trahunt