¿Hay alguna forma de excluir una dependencia de Maven a nivel mundial?

92

Estoy tratando de encontrar una forma "genérica" ​​de excluir una dependencia transitiva para que no se incluya sin tener que excluirla de todas las dependencias que dependen de ella. Por ejemplo, si quiero excluir slf4j, hago lo siguiente:

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

Esto es en parte para limpiar el archivo pom, en parte para evitar problemas en el futuro con personas que agregan dependencias que dependen de esa dependencia excluida y se olvidan de excluirla.

¿Hay alguna manera?

Sébastien Le Callonnec
fuente
2
No resuelve el problema, pero maven-enforcer-plugin tiene una función de dependencias prohibidas que fallará en la compilación si se infiltran dependencias no deseadas. Sin embargo, aún tiene que excluirlas manualmente: - /
dnault
Una respuesta alternativa está disponible aquí: stackoverflow.com/a/39979760/363573
Stephan

Respuestas:

69

¿Esto ayuda? http://jlorenzen.blogspot.com/2009/06/maven-global-excludes.html

"Suponiendo que quiero excluir avalon-framework de mi WAR, agregaría lo siguiente a mis proyectos POM con un alcance de proporcionado. Esto funciona en todas las dependencias transitivas y le permite especificarlo una vez.

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

Esto incluso funciona cuando se especifica en el POM principal, lo que evitaría que los proyectos tuvieran que declarar esto en todos los POM secundarios ".

Joffer
fuente
49
Sigue siendo solo un truco parcial: la dependencia no terminará dentro del artefacto de compilación, pero aún está disponible durante las pruebas.
Tuukka Mustonen
@TuukkaMustonen ¿Qué pasa con el runtimealcance en lugar del providedalcance?
Stephan
¿Qué sucede si avalon-framework 4.1.3+ se incluye en otra parte del proyecto? Vea una respuesta aquí: stackoverflow.com/a/39979760/363573
Stephan
Ya no uso Maven, así que no estoy en condiciones de probar las otras respuestas, pero animo a la gente a que las considere en caso de que haya una que no sea un truco parcial, según @TuukkaMustonen
Joffer
18

Creé un frasco vacío y creé esta dependencia:

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

No es perfecto porque a partir de ahora tienes un jar vacío en tu ruta de compilación / prueba. Pero eso es solo cosmético.

Guus Bloemsma
fuente
3
systemel alcance ahora está en desuso: maven.apache.org/guides/introduction/…
Jason Young
Para evitar el uso del systemalcance, consulte el repositorio virtual de Maven versión99.grons.nl (Advertencia: solo HTTP) o (solo para commons-logging / log4j) consulte la "alternativa 3) artefactos vacíos" aquí: slf4j.org/faq.html#excluyendoJCL
seanf
16

Para ampliar el comentario de dnault :

Se puede usar la regla de dependencias prohibidas del complemento Maven Enforcer para garantizar que se excluyan las dependencias. Aún hay que excluirlos manualmente, pero la compilación fallará si alguien agrega la dependencia en otro lugar por error.

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

También hay una solicitud de función abierta: MNG-1977 Exclusiones de dependencia global

Arend contra Reinersdorff
fuente
2
Siguiendo su respuesta y leyendo la discusión del enlace que proporcionó, me di cuenta de que los frascos no deseados están entrando en fat jar algunas veces solo porque la versión de maven utilizada en local y en el servidor son diferentes, por lo que la lógica de empaquetado puede agregar versiones bastante diferentes de dependencias si no se aplican estrictamente. Para resolver mi problema similar utilicé spring-boot-maven-plugin configuration / excludes / exclude para <goal> reempaquetado </goal>.
Aprodan el
10

Como recordatorio, aquí está la respuesta de la documentación oficial de Maven:

Por qué las exclusiones se realizan por dependencia, en lugar de a nivel de POM

Esto se hace principalmente para asegurarse de que el gráfico de dependencia sea predecible y para evitar que los efectos de la herencia excluyan una dependencia que no debe excluirse. Si llega al método de último recurso y tiene que incluir una exclusión, debe estar absolutamente seguro de cuál de sus dependencias genera esa dependencia transitiva no deseada.

Si se quiere hacer una construcción más robusta, se puede utilizar un rango de versiones . Esto aseguraría que ninguna versión más nueva de la dependencia pueda interferir con el proyecto.

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

Cualquier versión de slf4j-api> = 1.4.2 se considerará ofrecida (proporcionada) en tiempo de ejecución, ya sea desde una ruta de clase configurada o desde un contenedor.

Referencias

Stephan
fuente