Does exists some way to avoid duplicated JARs with distinct groupId in maven without expliciting excluding the duplicates?
I have a maven bui开发者_运维百科ld which generates some duplicated JARs in classpath.
Here are some examples:
groupId: javax.xml.stream
artifactId: stax
version: 1.0-2
groupId: stax
artifactId: stax
version: 1.0.1
groupId: jboss
artifactId: javassist
version: 3.7.0 GA
groupId: javassist
artifactId: javassist
version: 3.9.0 GA
These JARs are not imported directly from my project, they are transitive dependencies. Since the groupId and artifactId of the different versions does not matches, maven thinks that they are independent.
I can hunt down (may be using some tool for that) these duplicates and exclude them explicitly in pom.xml. However I don't want to manually hunt them down and exclude them, because this defeats the automatic dependency managing from maven and is a nightmare when some dependency is upgraded and the transistive dependencies mismatches again. There exist some way to make maven smarter and fix this automatically?
Answering that. I found no way to make maven smarter and had to hunt down and manually exclude every duplicated dependency. Switching the repositories to use a set of repositories that does not messes up one to the other helps too, but this is not always possible and can have side-effects of breaking some dependencies.
There is a workaround using the relocation mechanism, though it may only work in certain environments.
In short relocation allows you to "redirect" all dependencies from e.g. javax.xml.stream:stax
to stax:stax
. The problem is, adding a relocation is nothing you can do in your own project. You have to add a new version to the original groupId
and artifactId
containing the relocation information. If you have a private (e.g. corporate) Maven repository you can add it there or if there are only few developers the developers local repository can be used. In other cases you are probably out of luck with this solution.
Now the details:
Create a new Maven project with a pom.xml
like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Coordinates of the artifact you want to replace -->
<groupId>javax.xml.stream</groupId>
<artifactId>stax</artifactId>
<!-- Some dummy version that would never be released -->
<version>relocate-to-stax</version>
<distributionManagement>
<relocation>
<!-- Coordinates of the new artifact -->
<groupId>stax</groupId>
<!-- artifactId stays the same → no need to specify again -->
</relocation>
</distributionManagement>
</project>
Add this to your repository (e.g. using mvn install
).
In your project add this new version for the artifact to the dependencyManagement
section:
<project>
<!-- ... -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.xml.stream</groupId>
<artifactId>stax</artifactId>
<version>relocate-to-stax</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
With this, all dependencies to javax.xml.stream:stax
will use the "version" relocate-to-stax
which will relocate to stax:stax:relocate-to-stax
. The only thing left to do is to add the desired version of the destination artifact to the dependencyManagement
:
<project>
<!-- ... -->
<dependencyManagement>
<dependencies>
<!-- ... -->
<dependency>
<groupId>stax</groupId>
<artifactId>stax</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
精彩评论