2
votes

I have a maven build 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?

2
Having run into a similar problem in the past, I think the best approach is to contact the project maintainers that are using "obsolete" dependencies, and ask them to update their projects.Anon

2 Answers

1
votes

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.

0
votes

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>