Clojure and Java + Maven form a great powerhouse in anyone’s stack. How to spot and resolve conflicting software is something that puzzled me for a bit. There are a few techniques to employ:
The main 'go-to-guy' is lein deps :tree in the /path/to/project/root (read: where the project.clj file is). This will compile a dependency tree which lists conflicting software e.g.
~/clj/kb/drijfveer λ lein deps :tree 12:12 susy@simbad
Possibly confusing dependencies found:
[com.cemerick/pomegranate "0.3.0"] -> [org.apache.maven/maven-aether-provider "3.0.4"] -> [org.codehaus.plexus/plexus-utils "2.0.6"]
overrides
[com.cemerick/pomegranate "0.3.0"] -> [org.apache.maven.wagon/wagon-http "2.2"] -> [org.apache.maven.wagon/wagon-http-shared4 "2.2"] -> [org.apache.maven.wagon/wagon-provider-api "2.2"] -> [org.codehaus.plexus/plexus-utils "3.0"]
and
[com.cemerick/pomegranate "0.3.0"] -> [org.apache.maven.wagon/wagon-http "2.2"] -> [org.apache.maven.wagon/wagon-provider-api "2.2"] -> [org.codehaus.plexus/plexus-utils "3.0"]
and
[com.cemerick/pomegranate "0.3.0"] -> [org.apache.maven.wagon/wagon-provider-api "2.2"] -> [org.codehaus.plexus/plexus-utils "3.0"]
Consider using these exclusions:
[com.cemerick/pomegranate "0.3.0" :exclusions [org.codehaus.plexus/plexus-utils]]
[com.cemerick/pomegranate "0.3.0" :exclusions [org.codehaus.plexus/plexus-utils]]
[com.cemerick/pomegranate "0.3.0" :exclusions [org.codehaus.plexus/plexus-utils]]
[com.cemerick/pomegranate "0.3.0"] -> [org.apache.maven.wagon/wagon-http "2.2"] -> [org.apache.httpcomponents/httpcore "4.1.2"]
overrides
[clj-webdriver "0.6.1-LOCAL" :exclusions [commons-codec commons-io]] -> [com.github.detro/phantomjsdriver "1.2.0"] -> [org.seleniumhq.selenium/selenium-java "2.41.0"] -> [org.seleniumhq.selenium/selenium-htmlunit-driver "2.41.0"] -> [net.sourceforge.htmlunit/htmlunit "2.13"] -> [org.apache.httpcomponents/httpmime "4.3.1"] -> [org.apache.httpcomponents/httpclient "4.3.1"] -> [org.apache.httpcomponents/httpcore "4.3"]
and
.....- Step 1
-
Execute
lein deps :tree - Step 2
-
Open project.clj in an editor e.g. LT or Emacs.
- Step 3
-
Look at the output and get info on which packages are having what kind of conflict. In our case, fairly obvious the culprit here is a dependency version mismatch between dependencies of separate packages we depend on.
- Step 4
-
Correct the error by supplementing the package as dependency in YOUR project explicitly first. I usually just take the highest version listed.
- Step 5
-
Save the project.clj and rerun
lein deps :tree. See if the errors are gone, or got even worse. MOVE AROUND the position of the dependency, usually it needs to be somewhere above the packages requiring it e.g.:
:dependencies [[org.clojure/clojure "1.6.0"]
[prismatic/plumbing "0.4.3"]
[org.codehaus.plexus/plexus-utils "3.0"]
[org.apache.httpcomponents/httpcore "4.3.2"]
[org.clojure/tools.reader "0.8.3"]
[cheshire "5.2.0"]
[org.json/json "20090211"]
[me.raynes/fs "1.4.6"]
[enlive "1.1.5"]
[clj-webdriver "0.6.1-LOCAL" :exclusions [ commons-codec commons-io ]]
[lein-light-nrepl "0.1.0"]
[com.cemerick/url "0.1.1"]
]- Step 6
-
If all else fails, try moving around the other packages a bit if it makes sense. ONLY THEN start adding
:exclusionsto try and resolve the conflict. Usually it shouldn’t be needed.
So once I did that, then I ran a lein ancient to see which outdated dependencies
were there, and set forth to rid the last :exclusions, the tree now looks like:
:dependencies [[org.clojure/clojure "1.6.0"]
[prismatic/plumbing "0.4.4"]
[commons-codec "1.9"]
[org.codehaus.plexus/plexus-utils "3.0.22"]
[org.apache.httpcomponents/httpcore "4.4.1"]
[org.clojure/tools.reader "0.9.2"]
[cheshire "5.5.0"]
[org.json/json "20090211"] ; do NOT change/update or webdriver breaks!
[me.raynes/fs "1.4.6"]
[enlive "1.1.5"]
[clj-webdriver "0.6.1-LOCAL"]
[lein-light-nrepl "0.1.0"]
[com.cemerick/url "0.1.1"]]Output is:
[alembic "0.3.2"]
[lein-as-resource "2.5.0" :exclusions [[org.clojure/clojure]]]
[org.flatland/classlojure "0.7.0" :exclusions [[org.clojure/clojure]]]
[org.tcrawley/dynapath "0.2.3" :exclusions [[org.clojure/clojure]]]
[backtick "0.3.2"]
[cheshire "5.5.0"]
[com.fasterxml.jackson.core/jackson-core "2.5.3"]
[com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.5.3"]
[com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.5.3"]
[tigris "0.1.1"]
[clj-webdriver "0.6.1-LOCAL"]
[clj-http "0.3.0" :exclusions [[org.apache.httpcomponents/httpclient] [org.apache.httpcomponents/httpcore] [org.apache.httpcomponents/httpmime]]]
[slingshot "0.10.1"]
[com.github.detro/phantomjsdriver "1.2.0"]
[org.clojure/tools.logging "0.2.3"]
[org.mortbay.jetty/jetty "6.1.25"]
[org.mortbay.jetty/jetty-util "6.1.25"]
[org.mortbay.jetty/servlet-api "2.5-20081211"]
[org.seleniumhq.selenium/selenium-java "2.43.0"]
[org.seleniumhq.selenium/selenium-chrome-driver "2.43.0"]
[org.seleniumhq.selenium/selenium-firefox-driver "2.43.0"]
[org.seleniumhq.selenium/selenium-htmlunit-driver "2.43.0"]
[net.sourceforge.htmlunit/htmlunit "2.15"]
[commons-collections "3.2.1"]
[net.sourceforge.cssparser/cssparser "0.9.14"]
[org.w3c.css/sac "1.3"]
[net.sourceforge.htmlunit/htmlunit-core-js "2.15"]
[net.sourceforge.nekohtml/nekohtml "1.9.21" :exclusions [[xerces/xercesImpl]]]
[org.apache.commons/commons-lang3 "3.3.2"]
[org.apache.httpcomponents/httpmime "4.3.3"]
[org.eclipse.jetty/jetty-websocket "8.1.15.v20140411"]
[org.eclipse.jetty/jetty-http "8.1.15.v20140411"]
[org.eclipse.jetty/jetty-io "8.1.15.v20140411"]
[org.eclipse.jetty/jetty-util "8.1.15.v20140411"]
[xalan "2.7.1" :exclusions [[xerces/xercesImpl]]]
[xalan/serializer "2.7.1"]
[xerces/xercesImpl "2.11.0"]
[xml-apis "1.4.01"]
[org.seleniumhq.selenium/selenium-ie-driver "2.43.0"]
[org.seleniumhq.selenium/selenium-safari-driver "2.43.0"]
[org.seleniumhq.selenium/selenium-support "2.43.0"]
[org.webbitserver/webbit "0.4.15"]
[io.netty/netty "3.5.5.Final"]
[org.seleniumhq.selenium/selenium-remote-driver "2.43.0"]
[cglib/cglib-nodep "2.1_3"]
[com.google.guava/guava "15.0"]
[net.java.dev.jna/jna "3.4.0"]
[net.java.dev.jna/platform "3.4.0"]
[org.apache.commons/commons-exec "1.1"]
[org.apache.httpcomponents/httpclient "4.3.4"]
[commons-logging "1.1.3"]
[org.seleniumhq.selenium/selenium-api "2.43.0"]
[org.seleniumhq.selenium/selenium-server "2.43.0"]
[mx4j/mx4j-tools "3.0.1"]
[net.jcip/jcip-annotations "1.0"]
[org.bouncycastle/bcpkix-jdk15on "1.48"]
[org.bouncycastle/bcprov-jdk15on "1.48"]
[org.mortbay.jetty/servlet-api-2.5 "6.1.9"]
[org.seleniumhq.selenium/jetty-rc-repacked "5"]
[org.seleniumhq.selenium/jetty-repacked "7.6.1"]
[org.yaml/snakeyaml "1.8"]
[clojure-complete "0.2.3" :scope "test" :exclusions [[org.clojure/clojure]]]
[com.cemerick/pomegranate "0.3.0"]
[org.apache.maven.wagon/wagon-http "2.2"]
[org.apache.maven.wagon/wagon-http-shared4 "2.2"]
[org.apache.maven.wagon/wagon-provider-api "2.2"]
[org.apache.maven/maven-aether-provider "3.0.4"]
[org.apache.maven/maven-model-builder "3.0.4"]
[org.codehaus.plexus/plexus-interpolation "1.14"]
[org.apache.maven/maven-model "3.0.4"]
[org.apache.maven/maven-repository-metadata "3.0.4"]
[org.codehaus.plexus/plexus-component-annotations "1.5.5" :exclusions [[junit]]]
[org.sonatype.aether/aether-api "1.13.1"]
[org.sonatype.aether/aether-connector-file "1.13.1"]
[org.sonatype.aether/aether-connector-wagon "1.13.1" :exclusions [[org.codehaus.plexus/plexus-utils]]]
[org.codehaus.plexus/plexus-classworlds "2.4"]
[org.sonatype.sisu/sisu-inject-plexus "2.2.3"]
[org.sonatype.sisu/sisu-inject-bean "2.2.3"]
[org.sonatype.sisu/sisu-guice "3.0.3" :classifier "no_aop" :exclusions [[javax.inject] [aopalliance]]]
[org.sonatype.aether/aether-impl "1.13.1"]
[org.sonatype.aether/aether-spi "1.13.1"]
[org.sonatype.aether/aether-util "1.13.1"]
[com.cemerick/url "0.1.1"]
[pathetic "0.5.0"]
[com.cemerick/clojurescript.test "0.0.4"]
[commons-codec "1.9"]
[enlive "1.1.5"]
[org.ccil.cowan.tagsoup/tagsoup "1.2.1"]
[org.jsoup/jsoup "1.7.2"]
[lein-light-nrepl "0.1.0"]
[clj-stacktrace "0.2.7"]
[commons-io "2.4"]
[fs "1.3.3"]
[ibdknox/analyzer "0.0.2"]
[ibdknox/tools.reader "0.8.1"]
[org.clojure/clojurescript "0.0-2202" :exclusions [[org.apache.ant/ant]]]
[com.google.javascript/closure-compiler "v20131014"]
[args4j "2.0.16"]
[com.google.code.findbugs/jsr305 "1.3.9"]
[com.google.protobuf/protobuf-java "2.4.1"]
[org.clojure/data.json "0.2.3"]
[org.clojure/google-closure-library "0.0-20140226-71326067"]
[org.clojure/google-closure-library-third-party "0.0-20140226-71326067"]
[org.mozilla/rhino "1.7R4"]
[me.raynes/fs "1.4.6"]
[org.apache.commons/commons-compress "1.8"]
[org.tukaani/xz "1.5"]
[org.apache.httpcomponents/httpcore "4.4.1"]
[org.clojure/clojure "1.6.0"]
[org.clojure/core.cache "0.6.4"]
[org.clojure/data.priority-map "0.0.4"]
[org.clojure/tools.nrepl "0.2.6" :scope "test" :exclusions [[org.clojure/clojure]]]
[org.clojure/tools.reader "0.9.2"]
[org.codehaus.plexus/plexus-utils "3.0.22"]
[org.json/json "20141113"]
[prismatic/plumbing "0.4.1"]
[de.kotka/lazymap "3.1.0" :exclusions [[org.clojure/clojure]]]
[prismatic/schema "0.4.2"]
[swiss-arrows "1.0.0"]
So the main idea is, if the compiler is confused about dependencies, make it so that there is no ambiguity/confusion.