Search code examples
maventransitive-dependency

How does Maven handle transitive dependencies inherited from parent?


Given the parent and child pom below and lib1 and lib2 both include the class foo.bar.Test.

parent pom

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>foo</groupId>
    <artifactId>foo-parent</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>my.transitive</groupId>
            <artifactId>lib1</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>

child pom

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>foo</groupId>
        <artifactId>foo-parent</artifactId>
        <version>1.0</version>
    </parent>
    <artifactId>foo-child</artifactId>
    <dependencies>
        <dependency>
            <groupId>my.transitive</groupId>
            <artifactId>lib2</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>

If I include foo-child as a dependency in myApp and instantiate foo.bar.Test, which version of the class would Maven resolve to? And why?

my app pom

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>myApp</artifactId>
    <groupId>myApp</groupId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>foo</groupId>
            <artifactId>foo-child</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>

Solution

  • The short answer would be: it depends on which one is found on the classpath first.

    Having 2 of the same classes packaged with an application is not ideal as it can lead to many difficult to debug errors... If your myApp project is just going to be a jar then it would be best to compile it using the same library as what is going to be available to it at runtime.

    I believe maven uses the order it is written to the pom to build. One way of looking at this would be to run the following command for myApp:

    mvn dependency:tree -Dverbose

    This will print the dependencies in the order that they should appear on the classpath per spec. You can always use exclusions to exclude any inherited library you might not want. Hope this helps.