In my project there is a class implementing an interface. The interface comes from a dependency. I have another dependency that itself has a dependency on a jar that also contains the same interface, except a version with more methods; the two jars containing the same package-interface DON'T have the same groupId or artifactId.
Compilation is failing because the compiler complains that the class in my project is not implementing all the methods. I realized it is because the compiler is taking the interface reference from the wrong jar. My question is, why is maven using the interface from the transitive dependency instead of the one from the jar that I explicitly mention in the project POM? I can see the jar that is used appears earlier in the definition (so i imagine in the classpath as well), but i thought in these cases maven resolved it by using the colliding class/interface from the dependency with the shortest path
Here is part of the dependency tree. Note that this is grepped but it can still be seen that javax.servlet:servlet-api
(the one actually used) is deeper in the tree compared to tomcat:servlet
(the one that should be used)
[builder@ca-rd-build11 proj]$ mvn dependency:tree | grep servlet
[INFO] | +- javax.servlet:servlet-api:jar:2.4:compile
[INFO] +- tomcat:servlet:jar:4.0.6:compile
I'm using maven 3.0.4
Hi, In our project we are using junit and jmockit for unit testing. Our project consists of several maven modules, hence the entire build process is defined with Maven poms.
Maven chooses the version of the dependency that is nearest in the dependency tree. This is explained very well in the Maven documentation: "nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg.
There are two types of dependencies in Maven: direct and transitive. Direct dependencies are the ones that we explicitly include in the project. On the other hand, transitive dependencies are required by direct dependencies. Maven automatically includes required transitive dependencies in our project.
Eclipse pom. xml “Dependency Hierarchy” tab shows the dependency tree of the project. It has two sides – the left side shows verbose output and the right side shows the resolved dependencies. We can use the “Filter” option to look for a specific dependency.
why is maven using the interface from the transitive dependency instead of the one from the jar that I explicitly mention in the project POM?
Because, to Maven, the two have nothing to do with each other. Maven doesn't know about class or package names, Maven just knows about groupId and artifactId. Since those are not the same, maven doesn't have any reason to omit the transitive dependency.
And if I am correct, Maven places the dependencies on the classpath in the order they are defined, i.e. the transitive dependencies of dependency a
appear before dependency b
.
When you declare your dependency on the other jar file you can tell it to exclude the transitive dependency on the conflicting jar file:
<dependency>
<groupId>group</groupId>
<artifactId>artifact</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>othergroup</groupId>
<artifactId>ArtifactToExclude</artifactId>
</exclusion>
</exclusions>
</dependency>
For future visitors (since the title is generic):
In Maven you have two categories of dependencies:
<dependencies>
As per the official Maven documentation the following mediation is applied when multiple versions are encountered as dependencies:
Maven picks the "nearest definition". That is, it uses the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, the first declaration wins.
Example: if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0.
In the above example, A is the actual project, B and E are external dependencies defined in its pom.xml file, and C and D are transitive dependencies.
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