ChatGPT解决这个技术问题 Extra ChatGPT

Is there a way to exclude a Maven dependency globally?

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?

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 :-/
An alternative answer is available here: stackoverflow.com/a/39979760/363573

R
Riccardo Cossu

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


It's still only a partial hack - the dependency won't end up inside the build artifact but it's still available during tests.
@TuukkaMustonen What about the runtime scope instead of provided scope?
What happen if avalon-framework 4.1.3+ is included elsewhere in the project? See a response here: stackoverflow.com/a/39979760/363573
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
A
Arend v. Reinersdorff

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


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 repackage.
2
2 revs

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.


system scope is now deprecated: maven.apache.org/guides/introduction/…
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
S
Stephan

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