Question

I have a project with a dependency on HTTP BUilder, this gives me the followoing dependency tree:

[INFO] +- org.codehaus.groovy.modules.http-builder:http-builder:jar:0.5.1:compile
[INFO] |  +- org.apache.httpcomponents:httpclient:jar:4.3.2:compile
[INFO] |  |  \- commons-codec:commons-codec:jar:1.6:compile
[INFO] |  +- net.sf.json-lib:json-lib:jar:jdk15:2.3:compile
[INFO] |  |  +- commons-beanutils:commons-beanutils:jar:1.8.0:compile
[INFO] |  |  +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] |  |  +- commons-lang:commons-lang:jar:2.4:compile
[INFO] |  |  \- net.sf.ezmorph:ezmorph:jar:1.0.6:compile
[INFO] |  +- net.sourceforge.nekohtml:nekohtml:jar:1.9.9:compile
[INFO] |  |  \- xerces:xercesImpl:jar:2.8.1:compile
[INFO] |  |     \- xml-apis:xml-apis:jar:1.3.03:compile
[INFO] |  \- xml-resolver:xml-resolver:jar:1.2:compile

After I add hibernate-entitymanager, the version of xml-apis:aml-apis changes. Suddenly Maven prefers to use version 1.0b2 which is a transitive dependency via dom4j:

[INFO] +- org.hibernate:hibernate-entitymanager:jar:4.3.1.Final:compile
[INFO] |  +- org.jboss.logging:jboss-logging:jar:3.1.3.GA:compile
[INFO] |  +- org.jboss.logging:jboss-logging-annotations:jar:1.2.0.Beta1:compile
[INFO] |  +- org.hibernate:hibernate-core:jar:4.3.1.Final:compile
[INFO] |  |  +- antlr:antlr:jar:2.7.7:compile
[INFO] |  |  \- org.jboss:jandex:jar:1.1.0.Final:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  |  \- xml-apis:xml-apis:jar:1.0.b2:compile

Due to this, I now get the following exception during runtime:

java.lang.IncompatibleClassChangeError: 
Class org.apache.xerces.parsers.AbstractSAXParser$LocatorProxy 
does not implement the requested interface org.xml.sax.Locator

I know I can fix it by manually adding the dependency with the good version number in my pom.xml, but I wonder why this is needed:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.3.03</version>
    </dependency>
Was it helpful?

Solution

By Default, when the same dependency is found in the dependency tree, Maven uses a closest one to the root.

In your case, this means

 org.hibernate:hibernate-entitymanager:jar:4.3.1.Final:compile
    \- dom4j:dom4j:jar:1.6.1:compile
       \- xml-apis:xml-apis:jar:1.0.b2:compile 

Vs

 org.codehaus.groovy.modules.http-builder:http-builder:jar:0.5.1:compile
    \- net.sourceforge.nekohtml:nekohtml:jar:1.9.9:compile
       \- xerces:xercesImpl:jar:2.8.1:compile
          \- xml-apis:xml-apis:jar:1.3.03:compile

Or to put it another way 3 levels deep vs 4 levels deep so 1.0.b2 wins.

To solve this, either exclude xml-apis from your dependency on hibernate-entitymanager or explicity declare a dependency on xml-apis (though you might have to play with this a bit, Xerces and its dependencies can be a nightmare to get aligned version-wise).

OTHER TIPS

It's needed because Maven cannot know which version it should choose, so Maven uses nearest-wins strategy to choose which one to use. Nearest-wins strategy is documented in Maven documentation.

In the dependency tee you've provided version 1.0.b2 is clearly the nearest, so the behaviour is working like designed.

You might want to look at this thread where this has been previously discussed (I couldn't decide if that thread is a duplicate of this or not)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top