How to Fix a Maven Dependency Loop (Used declared vs Unused declared)
I ran into a dependency loop of sorts in Maven when running mvn clean verify
.
Used undeclared dependencies found
I had the following dependency in my pom.xml
.
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client-api</artifactId>
</dependency>
Running mvn clean verify
would yield a Used undeclared dependencies found
warning.
[WARNING] Used undeclared dependencies found:
[WARNING] org.apache.hadoop:hadoop-common:jar:VERSION:compile
[WARNING] - org.apache.hadoop.fs.Path is referenced in com.some.package
[WARNING]
[WARNING] Unused declared dependencies found:
[WARNING] org.apache.hadoop:hadoop-client-api:jar:VERSION:compile
Unused declared dependencies found
Naturally, I followed the instructions: added the used undeclared dependency and removed the unused declared dependency.
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
</dependency>
But another run of mvn clean verify
yielded an Unused declared dependencies found
warning.
[WARNING] Unused declared dependencies found:
[WARNING] org.apache.hadoop:hadoop-common:jar:VERSION:compile
Dependency loop explanation
The first thing to note is that both of the artifacts hadoop-client-api
and hadoop-common
expose the aforementioned class org.apache.hadoop.fs.Path
.
This issue arises when the same class is being pulled from two different dependencies. One copy of the class is likely being directly exposed in one dependency and transitively exposed in another.
The dependency that appears first in the pom.xml
is the one that ends up loaded on the classpath.
Some dependencies need to be on the classpath in a certain order. Unfortunately, the wrong order will trigger this dependency loop.
First, we’ll want to isolate the artifact that’s also pulling in the specified class.
Printing out the dependency tree with mvn dependency:tree
will help identify that artifact (a child dependency is likely the one pulling in the overlapping set of files).
Once that artifact is found, we can simply reorder the dependencies such that the one that directly exposes the class comes first.