Fork me on GitHub

Ban Duplicate Classes

This rule checks the dependencies and fails if any class is present in more than one dependency.

The following parameters are supported by this rule:

  • ignoreClasses - a list of classes to ignore duplicates of. Wildcards can be specified using the * character.
  • findAllDuplicates - a boolean to indicate whether the rule should find all duplicates or fail fast at the first duplicate. Defaults to false.
  • ignoreWhenIdentical - when true indicates duplicate classes don't fail the build when their bytecode exactly matches each other. Defaults to false.
  • message - an optional message to provide when duplicates are found.
  • dependencies - a list of dependencies for which you want to ignore specific classes.
  • scopes - a list of scopes (e.g. test, provided) to include when scanning artifacts
  • ignoredScopes - a list of scopes (e.g. test, provided) to ignore when scanning artifacts
  • ignoreOptionals - a boolean, if true all dependencies which have <optional>true</optional> are ignored.
  • searchTransitive - a boolean, specify if transitive dependencies should be searched (default) or only look at direct dependencies.

Sample Plugin Configuration:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>3.4.1</version> <!-- find the latest version at http://maven.apache.org/plugins/maven-enforcer-plugin/ -->
        <executions>
          <execution>
            <id>enforce-ban-duplicate-classes</id>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <banDuplicateClasses>
                  <ignoreClasses>
                    <!-- example of ignoring one specific class -->
                    <ignoreClass>com.xyz.i18n.Messages</ignoreClass>

                    <!-- example of ignoring with wildcards -->
                    <ignoreClass>org.apache.commons.logging.*</ignoreClass>
                  </ignoreClasses>
                  <scopes>
                      <scope>compile</scope>
                      <scope>provided</scope>
                  </scopes>
                  <findAllDuplicates>true</findAllDuplicates>
                  <ignoreWhenIdentical>true</ignoreWhenIdentical>
                </banDuplicateClasses>
              </rules>
              <fail>true</fail>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>extra-enforcer-rules</artifactId>
            <version>1.8.0</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

You can even ignore classes per dependency if you'd like. For every dependency you can specify either the groupId, artifactId, type or classifier.
You can't specify the version, because once Maven has resolved the version of a specific dependency there's only one version available.
Note that you can use wildcard-expressions for these values, i.e. a '?' for one character and a '*' for any number of characters.

The configuration would look like this

<configuration>
  <rules>
    <banDuplicateClasses>
      <ignoreClasses>
        <ignoreClass>org.slf4j.*</ignoreClass>
      </ignoreClasses>
      <dependencies>
        <dependency>
          <artifactId>jcl-over-slf4j</artifactId>
          <ignoreClasses>
            <ignoreClass>org.apache.commons.logging.impl.*</ignoreClass>
          </ignoreClasses>
        </dependency>
        <dependency>
          <groupId>org.*</groupId>
          <artifactId>maven-*</artifactId>
          <type>*ar</type>
          <classifier>sources</classifier>
        </dependency>
      </dependencies>
    </banDuplicateClasses>
  </rules>
</configuration>

Trademarks

Apache, Apache Maven, Maven and the Apache feather logo are trademarks of The Apache Software Foundation.