URL: https://www.progressiverobot.com/maven-dependency-tree-resolving-conflicts/

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

dependency tree illustration for: 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](/community/tutorials/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.

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.

Further Reading: [Using Maven in Eclipse IDE](/community/tutorials/maven-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
$