Managing exceptions is an important aspect for the duplicate finder plugin. Often, third-party dependencies, that can not be changed have conflicts or include classes and resources that are duplicate with other classpath elements.
The duplicate finder plugin allows listing and excluding these conflicts.
<configuration>
<exceptions>
<exception>
<conflictingDependencies>
<dependency>
<artifactId>...</artifactId>
<groupId>...</groupId>
<version>...</version>
<type>...</type>
<classifier>...</classifier>
</dependency>
...
</conflictingDependencies>
<currentProject>false</currentProject>
<!-- Version 1.1.1+, removed in 2.0.0 -->
<bootClasspath>false</bootClasspath>
<!-- Version 1.1.1+, removed in 2.0.0 -->
<resourcePatterns>
<resourcePattern>...</resourcePattern>
</resourcePatterns>
<classes>
<class>...</class>
</classes>
<packages>
<package>...</package>
</packages>
<resources>
<resource>...</resource>
</resources>
</exception>
</exceptions>
</configuration>
Exception overview
Within the plugin configuration, one or more exceptions can be listed
in the <exceptions> element. Each exception is applied to all
classpath scopes (compile, runtime and test).
Each exception lists its conflicting dependencies in the conflictingDependencies
element and then optionally the specific conflicting classes and
resources. Any conflict covered by an exception will not be reported
or fail the build.
If an exception only contains a conflictingDependencies element (no
classes, packages, resources or resourcePatterns), any
duplicate between all the listed dependencies is ignored. If any of
these elements is present, only the listed classes or resources will
be ignored.
Warning! The presence of any of these elements will turn off the
wildcard behavior of an exception. Especially the presence of a
classes or packages element will also turn off the wildcard
behavior for resources and the presence of a resources or
resourcePatterns element will turn off the wildcard behavior for
classes. This was undefined in previous versions of the duplicate
finder plugin.
The conflictingDependencies element
The conflictingDependencies element lists all artifacts considered
for an exception as dependency elements. Each
dependency can be fully or partially defined.
The currentProject flag
The currentProject flag signals that the current project should be
added to the exception as a dependency. Any resource or class that is
duplicate between the current project and the listed dependencies will
be ignored.
The option is equivalent to having the current project listed as a
dependency in the conflictingDependencies element.
If the conflictingDependencies element already contains a dependency
for the current project, the flag has no effect.
Warning! This flag can lead to surprising behavior, especially if it is used in the root POM of a multi-module build or a parent pom. The ‘current project’ is evaluated at runtime and in a multi-module build it will be applied each time when the plugin is executed on a sub-project. It is recommended to use this flag specifically in the project POM where conflicts are expected.
Examples
In a mult-module build with two sub-projects, sub-project
sub-project-a has a conflict with commons-lang:commons-lang and
sub-project-b has a conflict with
commons-collections:commons-collections. It would be possible to
configure the duplicate finder plugin to ignore these by adding
exceptions to the project root POM:
<project>
<modules>
<module>sub-project-a</module>
<module>sub-project-b</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<configuration>
<exceptions>
<exception>
<currentProject>true</currentProject>
<conflictingDependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
</conflictingDependencies>
</exception>
<exception>
<currentProject>true</currentProject>
<conflictingDependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
</conflictingDependencies>
</exception>
</exceptions>
</configuration>
</plugin>
</plugins>
</build>
</project>
In this case, each of the sub projects (sub-project-a and
sub-project-b) will have any possible conflicts to
commons-lang:commons-lang and
commons-collections:commons-collections excluded. However, this
would also exclude possible conflicts between sub-project-a and
commons-collections:commons-collections or sub-project-b and
commons-lang:commons-lang even though each probably should have been
flagged.
A better way to solve this is moving the exceptions to the actual sub-project POMs:
Root POM:
<project>
<modules>
<module>sub-project-a</module>
<module>sub-project-b</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Sub-project POM sub-project-a:
<project>
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<configuration>
<exceptions>
<exception>
<currentProject>true</currentProject>
<conflictingDependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
</conflictingDependencies>
</exception>
</exceptions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Sub-project POM sub-project-b:
<project>
<build>
<plugins>
<plugin>
<groupId>org.basepom.maven</groupId>
<artifactId>duplicate-finder-maven-plugin</artifactId>
<configuration>
<exceptions>
<exception>
<currentProject>true</currentProject>
<conflictingDependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
</conflictingDependencies>
</exception>
</exceptions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Now, sub-project-a will have its conflicts with
commons-lang:commons-lang excluded and sub-project-b will have its
conflicts with commons-collections:commons-collections excluded
while any other conflict will still be flagged correctly.
The bootClasspath flag
** Available in plugin version 1.1.1, removed in 2.0.0! **
This flag only works up to JDK 8! As 2.0.0 no longer supports JDK 8, it was deprecated.
The bootClasspath flag signals that an exception to elements on the
boot classpath is defined. Any match between classes or resources in
the listed artifacts and the boot classpath elements is ignored.
This flag can be combined with the currentProject flag.
<exception>
<currentProject>false</currentProject>
<bootClasspath>false</bootClasspath>
</exception>
will ignore any conflict between classes and resources in the current project and the boot classpath.
Managing class exceptions with classes and packages
The classes and packages elements control which classes are
ignored by the duplicate finder plugin when determining conflicts.
Specific classes are listed as fully-qualified names in the classes
element and full packages are listed in the packages element. Any
package listed will match any class in that package and any
sub-package. This is a very powerful mechanism and it should be used
with care.
Examples
Exclude a set of classes that are copied around into different jars:
<exception>
<conflictingDependencies>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils-core</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
</conflictingDependencies>
<!-- Well done, Apache! -->
<classes>
<class>org.apache.commons.collections.ArrayStack</class>
<class>org.apache.commons.collections.Buffer</class>
<class>org.apache.commons.collections.BufferUnderflowException</class>
<class>org.apache.commons.collections.FastHashMap</class>
</classes>
</exception>
Exclude a package that was copied into a jar:
<exception>
<conflictingDependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>(,4.11)</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</dependency>
</conflictingDependencies>
<packages>
<package>org.hamcrest</package>
</packages>
</exception>
Manging resource exceptions with resources and resourcePatterns
The resources and resourcePatterns elements control which
resources are ignored. Similar to the class elements classes and
packages, resource lists single resource elements and
resourcePatterns can match one or many resources.
A specific resource is listed with its full path in the resources
element. Any resource listed should be fully qualfied and start with a
/. For backwards compatibility, relative resource names (without a
leading /) are accepted but internally treated like absolute
resource names.
The resourcePatterns element accepts any standard Java regular
expression. Resource names are matched against these expressions. If
relative matching is not desired, a pattern must be anchored with
either a a start anchor (^) or an end anchor ($).
Examples
Exclude a specific resource that is duplicate in the Jersey jars:
<exception>
<conflictingDependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
</conflictingDependencies>
<resources>
<resource>/META-INF/jersey-module-version</resource>
</resources>
</exception>
