Tuesday, December 16, 2008

View maven dependency tree

A project's dependency tree can be expanded to display dependency conflicts. For example, to find out why Commons Collections 2.0 is being used by the Maven Dependency Plugin, we can execute the following in the project's directory:
mvn dependency:tree -Dverbose -Dincludes=commons-collections

The verbose flag instructs the dependency tree to display conflicting dependencies that were omitted from the resolved dependency tree. In this case, the goal outputs:
[INFO] [dependency:tree]
[INFO] org.apache.maven.plugins:maven-dependency-plugin:maven-plugin:2.0-alpha-5-SNAPSHOT
[INFO] +- org.apache.maven.reporting:maven-reporting-impl:jar:2.0.4:compile
[INFO] | \- commons-validator:commons-validator:jar:1.2.0:compile
[INFO] | \- commons-digester:commons-digester:jar:1.6:compile
[INFO] | \- (commons-collections:commons-collections:jar:2.1:compile - omitted for conflict with 2.0)
[INFO] \- org.apache.maven.doxia:doxia-site-renderer:jar:1.0-alpha-8:compile
[INFO] \- org.codehaus.plexus:plexus-velocity:jar:1.1.3:compile
[INFO] \- commons-collections:commons-collections:jar:2.0:compile

Thus we can see that Commons Collections 2.0 was chosen over 2.1 since it is nearer, and by default Maven resolves version conflicts with a nearest-wins strategy.

More specifically, in verbose mode the dependency tree shows dependencies that were omitted for: being a duplicate of another; conflicting with another's version and/or scope; and introducing a cycle into the dependency tree.

http://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html

If the confliction jar files are on the same level, the one declared on the top in pom will win.
Here is the testing pom.xml
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.jencks</groupId>
<artifactId>jencks</artifactId>
<version>2.1</version>
</dependency>

Both of them depend on commons-collection. If we run the command to view the dependency tree, it looks like this
[INFO] [dependency:tree]
[INFO] example.activemq:activeMQ:jar:1.0-SNAPSHOT
[INFO] +- commons-digester:commons-digester:jar:1.7:compile
[INFO] | +- commons-beanutils:commons-beanutils:jar:1.6:compile
[INFO] | | \- (commons-collections:commons-collections:jar:2.0:compile - omitted for conflict with 2.1)
[INFO] | \- commons-collections:commons-collections:jar:2.1:compile
[INFO] \- org.jencks:jencks:jar:2.1:compile
[INFO] +- (commons-collections:commons-collections:jar:3.1:compile - omitted for conflict with 2.1)
[INFO] \- commons-dbcp:commons-dbcp:jar:1.2:runtime
[INFO] \- (commons-collections:commons-collections:jar:2.1:runtime - omitted for duplicate)

Both dependencies of commons-collections jar file are on the same level. But as commons-digester is declared on the top in pom.xml, maven will pick up the dependency from commons-digester.
If we change the sequence in pom.xml like this
<dependency>
<groupId>org.jencks</groupId>
<artifactId>jencks</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.7</version>
</dependency>

Then the tree will like this
[INFO] [dependency:tree]
[INFO] example.activemq:activeMQ:jar:1.0-SNAPSHOT
[INFO] +- org.jencks:jencks:jar:2.1:compile
[INFO] | +- commons-collections:commons-collections:jar:3.1:compile
[INFO] | \- commons-dbcp:commons-dbcp:jar:1.2:runtime
[INFO] | \- (commons-collections:commons-collections:jar:2.1:runtime - omitted for conflict with 3.1)
[INFO] \- commons-digester:commons-digester:jar:1.7:compile
[INFO] +- commons-beanutils:commons-beanutils:jar:1.6:compile
[INFO] | \- (commons-collections:commons-collections:jar:2.0:compile - omitted for conflict with 3.1)
[INFO] \- (commons-collections:commons-collections:jar:2.1:compile - omitted for conflict with 3.1)

This time maven get the commons-collections from jencks instead of commons-digester.

There is another link about maven conflict resolver http://docs.codehaus.org/display/MAVEN/Conflict+Resolvers
In order to preserve the 2.0.x POM schema, a POM property will initially be used to configure the ConflictResolver chain. The POM property will be named mavenConflictResolvers and its value will be defined as a comma-separated list of conflict resolver names. For example:
<properties>
<mavenConflictResolvers>newest,nearest</mavenConflictResolvers>
</properties>


For 2.1.x, it is likely that the POM schema will be modified to introduce a more appropriate syntax for configuring conflict resolvers. For example:
<dependencies>
<conflictResolvers>
<conflictResolver>newest</conflictResolver>
<conflictResolver>nearest</conflictResolver>
</conflictResolvers>
</dependencies>

No comments:

Post a Comment