I have a project, P1, that creates a jar. That project has a parent POM, P1-PARENT. P1-Parent includes the following:
<dependencyManagement>
<!-- Kafka uses Zookeeper 3.3.4, but Curator requires 3.4.5. To resolve
we specify 3.4.5 so all projects using either Kafka or Curator will
get the later version which is compatible with both projects. -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.10</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.2.0-incubating</version>
</dependency>
<!-- A bunch of other irrelevant stuff here -->
</dependencyManagement>
This works - the output of "mvn dependency:tree" includes:
[INFO] +- org.apache.kafka:kafka_2.10:jar:0.8.0:compile
[INFO] | +- org.apache.zookeeper:zookeeper:jar:3.4.5:compile (version managed from 3.3.4)
Note that this is the only dependency on zookeeper (verified via "mvn dependency:tree | grep zoo".
I have several other projects that also inherit from P1-PARENT and everything works fine, they all pull in ZooKeeper 3.4.5. However, A coworker of mine recently starting using P1 in one of their projects. Their project doesn't inherit from P1-PARENT. The transitive dependency they get from P1 is ZooKeeper 3.3.4, not 3.4.5. We have verified, via "mvn dependency:tree", that they get zookeeper.3.3.4 as a transitive dependency of Kafka (e.g. the output looks identical to what I've pasted above, but the version is 3.3.4 and it doesn't include the "(version managed ..." bit). Also, like my projects, the only dependency they have on ZooKeeper (transitive or otherwise) is through P1 (verified by dependency:tree and grep). The question is, why. When they include P1, shouldn't maven look at P1's parent POM when determining the transitive dependencies of P1?
I'm using Maven 3.0.5. They're using versions 3.0.3 and 3.1.1 and see the problem with both of those versions.
Maven doesn't resolve the version transitive dependency issue in this case.
This issue can be used by using maven bom concept.
Check the maven documentation for bom in the below link
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management
Here is another blog which explains usage of bom's
http://howtodoinjava.com/maven/maven-bom-bill-of-materials-dependency/
In your case to solve this issue, you need to add a dependency of your parent pom in the dependencyManagement section of other project where you are facing the issue.
When using Maven3, ensure you're using the right version of the maven-dependency-plugin by calling it by its fully qualified name: org.apache.maven.plugins:maven-dependency-plugin:2.8:tree. IIRC up to 2.6 gave a wrong tree. In such cases the advice was: run your project as 'mvn validate -X' to see the tree as resolved by Aether, the dependency management framework for Maven.
Related
I have a persistent problem with maven dependencies version changes in IntelliJ. Whenever I try to use a previous version of a library and change the dependency version in my pom.xml nothing happens. Maven continues to use the newer version of the library.
For example I want to use:
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
But Maven repo has version 2.0.2 saved :
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
So for my projects version 2.0.2.RELEASE is used.
I tried reimporting the project first. Then I tried "reimpor all maven projects". Then I checked Settings > Maven > Always update snapshots. I also tried opening the project settings and deleting the dependency from there, but on reimport the 2.0.2 version will be imported in the project. For now the only thing that works is deleting manually the folder from the ".m2" folder.
Shouldn't library versions be strictly followed and shouldn't version 2.0.1 v be used for my project?
The moment you change the version of the artifacts, maven will use the same version. It will never use neither new version nor the older version. Since you are using intellij, you can check which are the jar files along with their version used. See below the screenshot.
You can expand the External libraries as shown below and you can check the dependencies used in pom.xml.
Besides, you can also check in command prompt. Go to command prompt and point to the project directory and type the following command.
mvn install dependency:copy-dependencies
You can see all the required dependencies along with version information in target folder.
I suggest you not to delete the .m2 directory as you may have to download all the dependencies once again.
If you want to enforce the use of a particular dependency version you can use:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
What this will do is exclude the dependency unless it actually gets used, and then if it does gets used it only uses the version you have specified.
Not clear what is the issue.
Repo can contain everything, no matter if dependency is present locally.
Also, Idea does not resolve dependency itself, we use maven api to resolve them.
By default, maven takes dependency which is nearest to root (see https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html)
Specifiying explicit dependency in root pom should force using this version.
Could you please provide mvn dependency:tree output and corresponding IDEA maven dependency diagram (if you have IU)?
If Idea resolve another dependency version than maven, please fill an issue at https://youtrack.jetbrains.com/issues
Spring data gemfire 1.7.0.RELEASE has compile time dependencies on version 1.7.12 of slf4j-api and jcl-over-slf4j. I have defined the below dependencies in my maven pom file, as we need slf4j 1.7.10 dependency (few other jars depend on this):
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.10</version>
<scope>runtime</scope>
</dependency>
I have an internal maven repo as the Maven central repository. Below is the behavior I see in different scenarios, based on what jars are available in the maven central:
My questions:
In scenario 1, I don't understand why the build didn't complain about missing 1.7.12 jar. How did the dependency get resolved?
In scenario 2, how's the 1.7.10 jar overriding the 1.7.12 without me specifying an exclusion for slf4j 1.7.12 in the spring data dependency?
In scenario 3, when the pom for slf4j-parent 1.7.12 is missing in Maven central, why does it complain? Since 1.7.10 jars are present, shouldn't the build run fine picking up the 1.7.10 jars (similar to scenario 1)?
The answer is based on the Maven Dependencies Mediation mechanism, specifically this statement:
You can always guarantee a version by declaring it explicitly in your project's POM
So, essentially, by explicitly declaring it as part of your dependencies, you are overriding any version on transitive dependencies, as such you don't need to add any exclusion. You declare it, you have the knowledge of the project, Maven trusts you.
So in scenario 1 and 2 Maven applied the rule above and just followed what is specified in the POM.
In scenario 1, since it didn't find any 1.7.12 version at all, it even didn't try to resolve it and trusted your POM.
In scenario 2, it resolved the dependencies tree of 1.7.12, but then based on your POM, the version 1.7.10 won.
In scenario 3 it couldn't resolve the whole dependency tree of version 1.7.12 and as such it gave an error: yes, the version from your POM would have won anyway, but since Maven had an error on getting the full dependency tree, it then failed its execution.
This is a special case though, and final confirmation could only be given looking at the concerned code of the Maven version you are using.
Update
What I would suggest to try in the three scenarios to have a bit more of details, is to run from the console:
mvn dependency:resolve -Dsort=true -X
Thanks to the debug flag, it will provide a list of included and excluded dependencies during the Dependency Mediation process.
As a complement, running:
mvn dependency:tree
Would give you the full dependency graph, showing what was actually taken from the POM and what came through transitive dependencies. That might give you further info. For further details, I would suggest to have a look at the Maven Dependency Plugin goals.
Project A references Project B. Project B has included a local dependency. This local dependency unfortunately has a dependency to net.java.dev.designgridlayout in version 1.5.
We want to use net.java.dev.designgridlayout in version 1.11 in Project A but we are not able to "overwrite" the dependency. Eclipse always uses the dependency from Project B.
We already tried to exclude the 1.5 version from the local dependency, but it doesn't work.
The strange thing is, that Eclipse successfully resolves a class that has been added with version 1.11. For an already existing class, however, eclipse resolves it from the transitive dependency from de.someCompany.
Project B:
<dependencies>
<dependency>
<groupId>de.someCompany</groupId>
<artifactId>fs-client</artifactId>
<version>5.1.209</version>
<exclusions>
<exclusion>
<groupId>net.java.dev.designgridlayout</groupId>
<artifactId>designgridlayout</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.java.dev.designgridlayout</groupId>
<artifactId>designgridlayout</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
Project A:
<dependencies>
<dependency>
<groupId>Project-B</groupId>
<artifactId>Project-B</artifactId>
<version>1503.01</version>
</dependency>
</dependencies>
I also tried to include the 1.11 dependency in Project A.
We even tried to install the DesignGridLayout V. 1.11 in the local dependency and to change the groupID and artifactId to something different, but it cannot even be found by Eclipse for some reason. If it would be possible to include the DesignGridLayout with another groupId and artifactId, I think it would work.
mvn install:install-file -Dfile=lib\designgridlayout.jar -DgroupId=com.company.designgridlayout -DartifactId=design-grid-layout -Dversion=1.11 -DgeneratePom=true -Dpackaging=jar -DlocalRepositoryPath="%USERPROFILE%\.m2\repository"
Not sure - but:
Your project A has a dependency to itself? Shouldn't it use project-b?
Its not a good idea to change group or artifact id's as maven can no longer detect its the same artifact. If you do a custom version the version number should be enough.
If you add the dependency in your own pom then you don't need to exclude the artifact, since the groupId and artifactId are the same. The version in your own pom will win in project-b. If project a defines that dependency again itself that version will win.
I would do a mvn dependency:tree on project-a pom to see where the dependencies come from.
For eclipse: it indexes the local repository. In the maven settings there is a re-index button. So if you manually copy jars in there that may help eclipse to find the artifact. But that workaround would need to be done on every machine. I would not count that as solution. In the maven world artifact-resolution is an infrastructure issue and should not be handled per project. The way this is done should be transparent through the settings.xml
I have a maven project in eclipse with m2e plugin. Dependency hierarchy is showing it is omitting spring 3.2.3 in place of 3.0.0.RELEASE as shown below. How to do it otherwise? Should it not omit the older version and keep the latest?
Maven works on the principle of nearest wins strategy while resolving the dependency conflicts , that means whichever version it finds nearer in the tree , it will take that version and ignore the other versions.
In your case when you can run -
mvn dependency:tree -Dverbose -Dincludes=spring-aop
You will notice that in the tree hierarchy version 3.0.0 is coming earlier in comparison to version 3.2.3 , so that's why it is taking version 3.0.0 version for resolving the dependency.
Solution : As a recommended solution to these types of problem is have a proper dependency management in your parent pom.xml file. Like in your case you can have something lik e this :
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.3</version>
</dependency>
<dependencies>
</dependencyManagement>
Now no matter what whenever Maven try to resolve the version for spring-aop , it will always consult the dependency management and will use the version defined under dependencyManagement.
For more you can refer here on my blog: how maven resolves dependency conflicts
I have a dependency that I have added to my project:
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-server</artifactId>
<version>7.0.5</version>
</dependency>
When I compile and run I get an error indicating a mismatch of signatures. Looking at my Maven Dependencies in my Java Build Path (Eclipse) I see a jar being added by Maven for Vaadin version 6.8.8. I have scoured my pom.xml and do not see that I have added that. I assume that this dependency is being added by another dependency.
I definitely want to use Vaadin version 7.0.5. As long as version 6.8.8 keeps getting included it will be an issue. How can I resolve this?
mvn dependency:tree
Once you have its output you can add a suitable exclusion.