Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Maven choose version 1.0.b2 over 1.3.03

Tags:

java

maven

xerces

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>
like image 996
Wim Deblauwe Avatar asked Apr 24 '14 11:04

Wim Deblauwe


2 Answers

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).

like image 167
Nick Holt Avatar answered Oct 24 '22 09:10

Nick Holt


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)

like image 43
eis Avatar answered Oct 24 '22 09:10

eis