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
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client-api</artifactId> </dependency>
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-common expose the aforementioned class
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.