Is there a way to exclude a Maven dependency globally?

63,562

Solution 1

Does this help? http://jlorenzen.blogspot.com/2009/06/maven-global-excludes.html

"Assuming I want to exclude avalon-framework from my WAR, I would add the following to my projects POM with a scope of provided. This works across all transitive dependencies and allows you to specify it once.

<dependencies>
  <dependency>
      <artifactId>avalon-framework</artifactId>
      <groupId>avalon-framework</groupId>
      <version>4.1.3</version>
      <scope>provided</scope>
  </dependency>
</dependencies>

This even works when specifying it in the parent POM, which would prevent projects from having to declare this in all child POMs."

Solution 2

To expand on dnault's comment:

One can use the Maven Enforcer plugin's Banned Dependencies rule to ensure dependencies are excluded. One still has to exclude them manually, but the build will fail if anyone adds the dependency elsewhere by mistake.

<dependencies>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jmx</artifactId>
    <version>3.3.2.GA</version>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.4.1</version>
    <executions>
      <execution>
        <goals>
          <goal>enforce</goal>
        </goals>
        <configuration>
          <rules>
            <bannedDependencies>
              <excludes>
                <exclude>org.slf4j:slf4j-api</exclude>
              </excludes>
            </bannedDependencies>
          </rules>
        </configuration>
      </execution>
    </executions>
  </plugin>
</plugins>

Also there is an open feature request: MNG-1977 Global dependency exclusions

Solution 3

I created an empty jar and created this dependency:

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <scope>system</scope>
    <systemPath>${basedir}/src/lib/empty.jar</systemPath>
    <version>0</version>
</dependency>

It is not perfect because from now on you have an empty jar in your compile/test path. But that is just cosmetic.

Solution 4

As a reminder, here is the answer from Maven official documentation:

Why exclusions are made on a per-dependency basis, rather than at the POM level

This is mainly done to be sure the dependency graph is predictable, and to keep inheritance effects from excluding a dependency that should not be excluded. If you get to the method of last resort and have to put in an exclusion, you should be absolutely certain which of your dependencies is bringing in that unwanted transitive dependency.

If one wants to make a build more robust, a version range can be used. This would ensure that no newer version of the dependency can interfere with the project.

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>[1.4.2,)</version>
   <scope>provided</scope>
</dependency>

Any slf4j-api version >= 1.4.2 will be considered as offered (provided) at runtime, either from a configured classpath or a container.

References

Share:
63,562

Related videos on Youtube

Sébastien Le Callonnec
Author by

Sébastien Le Callonnec

Ruby enthusiast, JRuby contributor.

Updated on July 08, 2022

Comments

  • Sébastien Le Callonnec
    Sébastien Le Callonnec almost 2 years

    I’m trying to find a “generic” way of excluding a transitive dependency from being included without having to exclude it from all the dependencies that depend on it. For example, if I want to exclude slf4j, I do the following:

      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jmx</artifactId>
        <version>3.3.2.GA</version>
        <exclusions>
          <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.4.0.GA</version>
        <type>jar</type>
        <exclusions>
          <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
    

    This is partly to clean up the pom file, partly to avoid issues in the future with people adding dependencies that depend on that excluded dependency — and forgetting to exclude it.

    Is there a way?

    • dnault
      dnault about 8 years
      Doesn't solve the problem, but maven-enforcer-plugin has a banned dependencies feature that will fail the build if unwanted dependencies sneak in. You still have to manually exclude them, though :-/
    • Stephan
      Stephan over 7 years
      An alternative answer is available here: stackoverflow.com/a/39979760/363573
  • Tuukka Mustonen
    Tuukka Mustonen over 12 years
    It's still only a partial hack - the dependency won't end up inside the build artifact but it's still available during tests.
  • Stephan
    Stephan over 7 years
    @TuukkaMustonen What about the runtime scope instead of provided scope?
  • Stephan
    Stephan over 7 years
    What happen if avalon-framework 4.1.3+ is included elsewhere in the project? See a response here: stackoverflow.com/a/39979760/363573
  • Joffer
    Joffer almost 7 years
    I don't use Maven anymore so I'm not in a position to test the other answers, but I'd encourage folks to consider them in case there's one that isn't a partial hack, as per @TuukkaMustonen
  • aprodan
    aprodan over 5 years
    Following your answer and reading discussion from link you provided I realized unwanted jars are coming into fat jar some times just because maven version used on local and on server are different so packaging logic can add quite different versions of dependencies if they are not strictly enforced. To solve my similar problem I used spring-boot-maven-plugin configuration/excludes/exclude for <goal>repackage</goal>.
  • Jason Young
    Jason Young over 4 years
    system scope is now deprecated: maven.apache.org/guides/introduction/…
  • seanf
    seanf almost 4 years
    To avoid using system scope, see the virtual Maven repository version99.grons.nl (Warning: HTTP only) or (for commons-logging/log4j only) see "alternative 3) empty artifacts" here: slf4j.org/faq.html#excludingJCL