Now, one of the things that I wasted quite some time on is excluding a dependency. One of our modules is defining a dependency to Apache DBCP framework like this:
<dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.1</version> </dependency>This dependency is transitively depending on some XML artifacts, which you can see by using the maven-dependency-plugin's tree goal:
... [INFO] +- commons-dbcp:commons-dbcp:jar:1.2.1:compile [INFO] +- commons-pool:commons-pool:jar:1.2:compile [INFO] +- xml-apis:xml-apis:jar:1.0.b2:compile [INFO] \- xerces:xercesImpl:jar:2.0.2:compile ...Well, the xml-apis and xerces artifacts are a bit outdated and actually we didn't want them at all in our war files, so I decided to exclude them using the dependency exclusion feature:
<dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.1</version> <exclusions> <exclusion> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> </exclusion> <exclusion> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> </exclusion> </exclusions> </dependency>What do you think will be the result? Surprisingly,
xml-apis:xml-apis
vanished, but xerces:xercesImpl
didn't. The new dependency tree is the evidence:... [INFO] +- commons-dbcp:commons-dbcp:jar:1.2.1:compile [INFO] +- commons-pool:commons-pool:jar:1.2:compile [INFO] \- xerces:xercesImpl:jar:2.0.2:compile ...That's strange, isn't it? It took me an hour or so playing around to find the reason for this behaviour: Xerces has been relocated with respect to its Maven coordinates... The only hint Maven is giving you is this message when executing in debug mode:
[DEBUG] While downloading xerces:xerces:2.0.2 This artifact has been relocated to xerces:xercesImpl:2.0.2.What does that mean? Well, you may relocate artifacts in the Maven repository when the group or artifact id should change (for more details, see the Guide to Relocation). Originally, the DBCP artifact specified a dependency to
xerces:xerces
in its dependencies – which you can see in the artifact's POM file (residing in your local Maven cache, for instance):<dependency> <groupId>xerces</groupId> <artifactId>xerces</artifactId> <version>2.0.2</version> </dependency>However,
xerces:xerces
has been relocated to xerces:xercesImpl
and these new coordinates are what is shown in the dependency tree. But, when excluding a dependency, you must specify the original transitive dependency (as defined by the artifact), not the new coordinates:<dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.1</version> <exclusions> <exclusion> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> </exclusion> <exclusion> <groupId>xerces</groupId> <artifactId>xerces</artifactId> </exclusion> </exclusions> </dependency>How intuitive is that???
Maven should really do better, either by indicating the original coordinates when showing the dependency tree/list, or better yet by issuing a warning when trying to exclude a relocated dependency. I guess the latter one is not easy to implement, but current solution is just annoying!