Search code examples
javamavendependencies

How can I ban only one transitive dependency in my maven project?


What I am trying currently is:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.4.1</version>
    <executions>
        <execution>
            <id>enforce-banned-dependencies</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <banTransitiveDependencies>
                        <excludes>
                            <exclude>*:*:*</exclude>
                        </excludes>
                        <includes>
                            <include>commons-lang:commons-lang:2.4</include>
                        </includes>
                    </banTransitiveDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

My intention with what I try above is:

Exclude banning all transitive dependencies, except commons-lang:2.4

When I try

mvn verify

I will get

[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-banned-dependencies) @ ebtam-core ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

which is not good. Because I know I have the following dependency in my project:

[INFO] +- org.apache.velocity:velocity:jar:1.6.2:compile
[INFO] |  +- commons-lang:commons-lang:jar:2.4:compile

What is it that I am doing wrong?


Solution

  • I don't see where this is documented but the problem is that the current build artifact is also considered when checking for the banTransitiveDependencies rules. Then, looking at the code, since this artifact is excluded, it won't check its dependencies. So when you specify * for the exclude pattern, the main artifact matches that and the rest of the includes rules are ignored. So the following would work:

    <rules>
        <banTransitiveDependencies>
            <excludes>
                <exclude>commons-lang</exclude>
            </excludes>
            <includes>
                <include>commons-lang:commons-lang:2.4</include>
            </includes>
        </banTransitiveDependencies>
    </rules>
    

    but it doesn't answer your question of "Exclude banning all transitive dependencies, except commons-lang:2.4".

    The question is, why are you using this rule in the first place? It was introduced in MENFORCER-138 and its goal is to force developers to not rely on transitive dependencies being inherited and force their declaration in the POM.

    Your goal here is to fail the build if the dependency commons-lang:commons-lang:2.4 is in the classpath. Therefore, you should use the bannedDependencies rule. By default, it searches dependencies transitively. The following will do what you want, i.e. ban only commons-lang:commons-lang:2.4:

    <rules>
        <bannedDependencies>
            <excludes>
                <exclude>commons-lang:commons-lang:2.4</exclude>
            </excludes>
        </bannedDependencies>
    </rules>