1

In have one child module testA that has a dependency on vaadin-client-compiler that depends on commons-lang3 version 3.1, it also depends on another child module testB which depends on commons-lang3 version 3.4.

I expect testA to use the 3.4 version because testB depends on it but it uses the 3.1 version. I can solve it by adding [] to the version in testB project but why does it happen? Why maven doesn't resolve the correct version without being forced?

MCVE:

Parent:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test</name>
    <packaging>pom</packaging>
    <modules>
        <module>testB</module>
        <module>testA</module>
    </modules>
</project>

Child that depends

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <version>7.6.8</version>
            <artifactId>vaadin-client-compiler</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
  <groupId>testB</groupId>
  <artifactId>testB</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
  <groupId>testA</groupId>
  <artifactId>testA</artifactId>
</project>

And the dependent child

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <groupId>testB</groupId>
  <artifactId>testB</artifactId>
  <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
  </dependencies>
</project>

1 Answers1

3

Per the Maven Documentation:

[Maven] will use the version of the closest dependency to your project in the tree of dependencies.

and

if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins.

So the answer to your question is - because you defined the vaadin-client-compiler dependency before the testB dependency and the dependency on commons-lang3 is the same depth in the tree from testA.

If you reverse the order of your dependencies in testA you'll see that it now pulls the 3.4 version of commons-lang3 (assuming you're using a version of Maven that is 2.0.9 or newer)

D.B.
  • 4,523
  • 2
  • 19
  • 39
  • 1
    Thanks, for some reason I thought maven takes the version of the dependency into consideration and uses the later one, that's how I would've implemented it. There is less chance for something to break if it would've been done this way. – Black Trans Woman May 02 '18 at 05:54
  • You're quite welcome, but I'm not sure that using the latest version lessens the risk of problems in any significant way. It really depends on how the developers wrote the code and whether they planned for and tested backward compatibility. – D.B. May 02 '18 at 16:30