Same artifact uses different versions of same dependency

Viewed 223

I am using maven enforcer plugin but I found this strange case of dependency convergence:

Dependency convergence error for commons-collections:commons-collections:3.2.1 paths to dependency are:
+-ProjectA:B:0.1
  +-commons-validator:commons-validator:1.6
    +-commons-beanutils:commons-beanutils:1.9.2
      +-commons-collections:commons-collections:3.2.1
and
+-ProjectA:B:0.1
  +-commons-validator:commons-validator:1.6
    +-commons-collections:commons-collections:3.2.2

And this is the dependency declaration:

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.6</version>
</dependency>

you can see that the same artifact uses different versions of the same dependency. How can this happen? also the only way to suppress the warning is by including the latest version of that dependency as a direct dependency in my pom.

Am I missing something?

2 Answers

From the dependency tree you see that commons-validator:commons-validator:1.6 directly depends on commons-collections:commons-collections:3.2.2, but has also a transitive dependency on commons-collections:commons-collections:3.2.1. Nothing unusual about that.

To resolve this you need to choose a version. Just follow the advice of khmarbaise and add an entry to the <dependencyManagement> section of your POM.

Above all that same artifact doesn`t use different versions of the same dependency.

+-ProjectA:B:0.1
  +-commons-validator:commons-validator:1.6
    +-commons-beanutils:commons-beanutils:1.9.2
      +-commons-collections:commons-collections:3.2.1
and
+-ProjectA:B:0.1
  +-commons-validator:commons-validator:1.6
    +-commons-collections:commons-collections:3.2.2

Dependency commons-validator:commons-validator:1.6 uses commons-collections:commons-collections:3.2.2 directly and commons-collections:commons-collections:3.2.1 transitively (dependency of an other dependency). Maven`s dependency mediation will resolve this conflict based on neares-newest principle. Take a look at these:
[1] Dependency Mechanism
[2] Dependency Mediation and Conflict Resolution

The maven-enforcer-plugin`s dependencyConvergence rule works fine. As the documentation says:

This rule requires that dependency version numbers converge. If a project has two dependencies, A and B, both depending on the same artifact, C, this rule will fail the build if A depends on a different version of C then the version of C depended on by B.

Because commons-validator (A) and commons-beanutils (B) depending on commons-collections (C) and those dependecies has different versions this behaviour is totally reasonable.

You decide what do you want to exactly do.

Keep using dependencyConvergence rule and resolve this error

In this case just define commons-collections, commons-logging and commons-validator in <dependencyManagement> section and put those dependencies as managed dependences in your project.

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>commons-validator</groupId>
                <artifactId>commons-validator</artifactId>
                <version>1.6</version>
            </dependency>
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>3.2.2</version>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </dependency>
    </dependencies>

I think it needs a lot of overwork and after a while your project model will be unmaintenable. On the other hand Dependency Mediation rule resolves this problem.

Use other rule e.g. requireUpperBoundDeps

This rule is designed to investigagte if a resolved dependency during a build is lower than all transitive dependeny declarations. E.g. it will fail if your project depending on commons-collections:3.0 but commons-validator requires newer version commons-collections:3.2.2

    <dependencies>
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>

Forget enforcer and trust in Dependency Mediation

Almost all cases this is the right decision because Dependency Mediation is works fine.

Related