Maven Dependency Tree is very helpful in understanding the project dependencies and resolving any conflicts because of different versions of a dependency.
How to get the Maven Dependency Tree of a Project
We can run mvn dependency:tree
command in the terminal to print the project dependency tree.
For our example, I will be using the Mockito Tutorial project. You can download the project from the GitHub repository.
We are interested only in the project dependencies. The pom.xml has declared the following project dependencies.
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.19.0</version>
<scope>test</scope>
</dependency>
<!-- TestNG Dependencies -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
</dependencies>
Let’s see the output when we run the maven dependency tree command.
$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] | +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] | +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] | +- org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] | | - org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] | - junit:junit:jar:4.12:test
[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] | +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] | | - org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] | - org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] | - org.mockito:mockito-core:jar:2.19.0:test
[INFO] | +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] | - org.objenesis:objenesis:jar:2.6:test
[INFO] - org.testng:testng:jar:6.14.3:test
[INFO] +- com.beust:jcommander:jar:1.72:test
[INFO] - org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.871 s
[INFO] Finished at: 2019-12-13T12:24:11+05:30
[INFO] ------------------------------------------------------------------------
$
The output is showing all the JARs being used to run this application. The output shows the dependencies groupId, artifactId, packaging, version, and scope.
Excluding a Dependency from the Maven Project Dependencies
If you look at the above dependency tree output, the JUnit 4 JAR is being pulled as a transitive dependency of junit-platform-runner
. If you are planning to use JUnit 5 for writing test cases, it’s a good idea to exclude JUnit 4 from the dependency to avoid any conflicts.
We can exclude JUnit 4 JAR from the project dependencies using the exclusions tag. It has to be added to the dependency that is responsible for pulling it.
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.2.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
Let’s run the dependency tree command again. It should not show JUnit 4 JARs now.
Maven Dependency Tree
Resolving Conflicts using Maven Dependency Tree Verbose Mode
When we build a maven project, the dependency version that is nearer to the project is selected. It can cause issues when you want a specific version but some other version is getting picked by the maven.
We can use mvn dependency:tree -Dverbose
command to print the dependency conflicts. It can help us in determining if there are any incompatibility issues with a JAR.
$ mvn dependency:tree -Dverbose
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] | +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] | +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] | | +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] | | - (org.junit.platform:junit-platform-engine:jar:1.2.0:test - omitted for duplicate)
[INFO] | - org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] | +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] | - org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] | - (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] | +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] | +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] | | +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] | | +- (org.junit.platform:junit-platform-commons:jar:1.2.0:test - omitted for duplicate)
[INFO] | | - org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] | - org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] | +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] | +- (org.opentest4j:opentest4j:jar:1.1.0:test - omitted for duplicate)
[INFO] | - (org.junit.platform:junit-platform-commons:jar:1.2.0:test - omitted for duplicate)
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] | +- org.mockito:mockito-core:jar:2.19.0:test
[INFO] | | +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] | | +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] | | - org.objenesis:objenesis:jar:2.6:test
[INFO] | - (org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test - omitted for conflict with 5.2.0)
[INFO] - org.testng:testng:jar:6.14.3:test
[INFO] +- com.beust:jcommander:jar:1.72:test
[INFO] - org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.018 s
[INFO] Finished at: 2019-12-13T12:58:07+05:30
[INFO] ------------------------------------------------------------------------
$
The output line (org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test – omitted for conflict with 5.2.0) tells us that this version of JAR is dropped in favor of another version.
If you want to use junit-jupiter-api
version 5.1.0, just add it to the project maven dependencies. Since Maven resolves version conflicts with a nearest-wins strategy, the direct dependencies are always included in the project.
Filtering the Maven Dependency Tree
If the maven project has a lot of dependencies, it becomes hard to look for a specific artifact.
-Dincludes
We can use the -Dincludes
option to include only specific dependencies from the output.
The syntax of the filtering pattern is [groupId]:[artifactId]:[type]:[version]
.
Each of the pattern segment is optional and supports full and partial * wildcards.
$ mvn dependency:tree -Dverbose -Dincludes=org.junit.jupiter:junit-jupiter-api
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] | - org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] - org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] - (org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test - omitted for conflict with 5.2.0)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.981 s
[INFO] Finished at: 2019-12-13T13:04:04+05:30
[INFO] ------------------------------------------------------------------------
$
-Dexcludes
This is used to remove given dependencies from the dependency tree output. The pattern is the same as -Dincludes
option.
We can use a comma to specify multiple patterns to include or exclude from the dependency tree.
$ mvn dependency:tree -Dexcludes=org.junit.jupiter:junit-jupiter-api
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] | +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] | +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] | - org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] | - org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] | - org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] | - org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] | - org.mockito:mockito-core:jar:2.19.0:test
[INFO] | +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] | - org.objenesis:objenesis:jar:2.6:test
[INFO] - org.testng:testng:jar:6.14.3:test
[INFO] +- com.beust:jcommander:jar:1.72:test
[INFO] - org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.925 s
[INFO] Finished at: 2019-12-13T13:55:22+05:30
[INFO] ------------------------------------------------------------------------
$
Maven Dependency Tree in Eclipse IDE
Eclipse pom.xml “Dependency Hierarchy” tab shows the dependency tree of the project. It has two sides – the left side shows verbose output and the right side shows the resolved dependencies. We can use the “Filter” option to look for a specific dependency.
Eclipse Pom Dependency Hierarchy
Further Reading: Using Maven in Eclipse IDE
Saving Dependency Tree to a File
We can use -DoutputFile option to specify the file to save the dependency tree output.
$ mvn dependency:tree -DoutputFile=dependency-tree.txt
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] Wrote dependency tree to: /Users/pankaj/Desktop/maven-examples/Mockito-Examples/dependency-tree.txt
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.862 s
[INFO] Finished at: 2019-12-13T15:27:51+05:30
[INFO] ------------------------------------------------------------------------
$
$ cat dependency-tree.txt
com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
+- org.junit.platform:junit-platform-runner:jar:1.2.0:test
| +- org.apiguardian:apiguardian-api:jar:1.0.0:test
| +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
| - org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
| - org.junit.platform:junit-platform-commons:jar:1.2.0:test
+- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
| +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
| | - org.opentest4j:opentest4j:jar:1.1.0:test
| - org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
+- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
| - org.mockito:mockito-core:jar:2.19.0:test
| +- net.bytebuddy:byte-buddy:jar:1.8.10:test
| +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
| - org.objenesis:objenesis:jar:2.6:test
- org.testng:testng:jar:6.14.3:test
+- com.beust:jcommander:jar:1.72:test
- org.apache-extras.beanshell:bsh:jar:2.0b6:test
$