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>
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).
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With