Is there a way to exclude a Maven dependency globa

2019-01-13 03:25发布

问题:

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?

回答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."



回答2:

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.



回答3:

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



回答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

  • Maven version range
  • Optional Dependencies and Dependency Exclusions