Excluir todas las dependencias transitivas de una sola dependencia.

221

En Maven2, para excluir una sola dependencia transitiva, tengo que hacer algo como esto:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

El problema con este enfoque es que tengo que hacer esto para cada dependencia transitiva aportada por sample-artifactB.

¿Hay alguna forma de usar algún tipo de comodín para excluir todas las dependencias transitivas a la vez en lugar de una por una?

pbreault
fuente
A veces es necesario usar una versión más reciente de la biblioteca, por ejemplo, Spring 2.5.6, pero algunas otras dependencias incluyen una versión anterior, por ejemplo, struts2-spring-plugin (2.1.6) incluye Spring 2.5.3. En tales escenarios, existe un requisito para la exclusión o anulación de la versión.
Vinod Singh
1
Usa Ivy. Es una broma.
Jake Toronto

Respuestas:

54

Para maven2 no hay una manera de hacer lo que usted describe. Para maven 3, hay. Si está utilizando Maven 3, consulte otra respuesta para esta pregunta

Para maven 2, recomendaría crear su propio pom personalizado para la dependencia que tiene sus <exclusiones>. Para proyectos que necesitan usar esa dependencia, establezca la dependencia a su pom personalizado en lugar del artefacto típico. Si bien eso no necesariamente le permite excluir todas las dependencias transitivas con una sola <exclusión>, solo le permite escribir su dependencia una vez y todos sus proyectos no necesitan mantener listas de exclusión innecesarias y largas.

Whaley
fuente
12
Recomiendo no hacer tu propio pom para evitar exclusiones. Esto hace que su construcción sea mucho menos portátil y reduce la comprensión.
Brian Fox el
1
En caso de que no mire más allá, acepte la respuesta: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski
@JakubBochenski, la respuesta que he dado es específica para maven 2, que es con lo que está etiquetada esta pregunta (en el momento en que escribí este comentario). Su enlace es relevante solo para Maven 3. Independientemente, he editado mi respuesta para enlazar con el enlace a la respuesta más altamente votada.
whaley
306

Lo que funcionó para mí (puede ser una característica más nueva de Maven) es simplemente hacer comodines en el elemento de exclusión.

Tengo un proyecto de varios módulos que contiene un módulo de "aplicación" al que se hace referencia en dos módulos empaquetados con WAR. Uno de esos módulos empaquetados con WAR realmente solo necesita las clases de dominio (y todavía no los he separado del módulo de la aplicación). Encontré esto para trabajar:

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>app</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

El comodín en groupId y artifactId excluye todas las dependencias que normalmente se propagarían al módulo utilizando esta dependencia.

enricopulatzo
fuente
99
El comodín * para grupo y artefacto parece estar funcionando en maven 3
nkr1pt
22
No sé cómo pudo encontrar esto funcionando, ya que Maven 3 advierte explícitamente sobre el uso del asterisco: [ADVERTENCIA] 'dependencies.dependency.exclusions.exclusion.groupId' para <artifcat_id> con el valor "*" no coincidir con un patrón de identificación válido. [ADVERTENCIA] Se recomienda encarecidamente solucionar estos problemas porque amenazan la estabilidad de su compilación. [ADVERTENCIA] Por esta razón, es posible que las futuras versiones de Maven ya no admitan la creación de proyectos mal formados. ¿Le importaría proporcionar alguna evidencia de que es compatible y puede utilizarse? De lo contrario, consideraría su comentario como extremadamente engañoso.
ᄂ ᄀ
77
Trabajó maravillosamente con Maven 3.0.4. Gracias un montón !
Evgeny Goldin
1
maven 3.0.4 -> no funcionó bien para mí. el jar resultante es muy diferente cuando uso asterix, o cuando excluyo explícitamente todas las dependencias directas. puede tener que ver con el hecho de que estoy usando maven-assembly-plugin para crear un tarro gordo. ¡En este caso, la sulotión sugerida no funciona!
gilad hoch
31
Este metodo es valido. Arreglaron
Ryan
32

Una cosa que he encontrado útil:

Si coloca la dependencia con las exclusiones en la sección de gestión de dependencias del POM principal para su proyecto, o en un POM de administración de dependencias importable, entonces no necesita repetir la exclusión (o la versión).

Por ejemplo, si su POM principal tiene:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

Luego, los módulos en su proyecto pueden simplemente declarar la dependencia como:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

El POM principal especificará tanto la versión como las exclusiones. Utilizo esta técnica para casi todos nuestros proyectos y elimina muchas repeticiones.

Joshua Davis
fuente
23

Hace tres años recomendé usar la Versión 99 No existe, pero ahora he descubierto una mejor manera, especialmente desde que la Versión 99 está fuera de línea:

En el POM principal de su proyecto, use maven-enforcer-plugin para fallar la compilación si la dependencia no deseada se arrastra a la compilación. Esto se puede hacer usando la regla de dependencias prohibidas del complemento :

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Luego, cuando eso le avise sobre una dependencia no deseada, excluya en la <dependencyManagement>sección del POM principal :

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

De esta manera, la dependencia no deseada no aparecerá accidentalmente (a diferencia de una <exclusion>que es fácil de olvidar), no estará disponible incluso durante el tiempo de compilación (a diferencia del providedalcance), no hay dependencias falsas (a diferencia de la Versión 99) y ' funcionará sin un repositorio personalizado (a diferencia de la Versión 99). Este enfoque incluso funcionará según la versión del artefacto, los clasificadores, el alcance o un ID de grupo completo; consulte la documentación para obtener más detalles.

Esko Luontola
fuente
Tenga en cuenta que al menos en Maven 3.1, <configuration>se ignora cuando se ejecuta el objetivo desde la línea de comandos y debe moverse hacia arriba directamente debajo <plugin>.
David Harkness
Acabo de encontrar lo que parece un error desagradable de Maven - versión 3.5.2. Tengo un proyecto con submódulos donde excluyo una dependencia en la <dependencyManagement>sección de los padres . Ejecutar un mvn dependency:treeen ese proyecto específico no tendrá la dependencia excluida en absoluto. Pero todos los proyectos que importen esa dependencia no honrarán al <exclusions>otro pom padre del proyecto: ¡el excluido se arrastrará! Tuve que pasar <exclusions>a cada módulo pom directamente.
cbaldan
11

Utilizo la siguiente solución alternativa: en lugar de tratar de excluir el artefacto en todas las dependencias apropiadas, dibujo la dependencia como "provista" en el nivel superior. Por ejemplo, para evitar enviar xml-apis "cualquier versión":

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Michael Zilbermann
fuente
6

Hay una solución alternativa para esto, si establece el alcance de una dependencia en tiempo de ejecución , se excluirán las dependencias transitivas. Sin embargo, tenga en cuenta que esto significa que debe agregar un procesamiento adicional si desea empaquetar la dependencia del tiempo de ejecución.

Para incluir la dependencia del tiempo de ejecución en cualquier paquete, puede usar el objetivo de copia del complemento de dependencia de maven para un artefacto específico .

Vendedor rico
fuente
1
Esto me ayudó a solucionar problemas con el compilador Dalvik de Android que no podía manejar algunas de las inclusiones transitivas de dos niveles, pero tuve que usarlo en <scope>provided</scope>lugar de hacerlo <scope>runtime</scope>.
Garret Wilson el
6

si necesita excluir todas las dependencias transitivas de un artefacto de dependencia que va a incluir en un ensamblaje, puede especificar esto en el descriptor para el complemento de ensamblaje:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>
Superole
fuente
3

Si desarrolla bajo Eclipse, puede buscar en el gráfico de dependencia del Editor POM (pestañas avanzadas habilitadas) la dependencia que desea excluir de su proyecto y luego:

haga clic derecho sobre él -> "Excluir Maven Artifact ..." y Eclipse hará la exclusión por usted sin la necesidad de averiguar en qué dependencia está vinculada la lib.

Tib
fuente
tenga en cuenta que esto solo funciona si está utilizando el complemento m2eclipse
Nicolas Mommaerts
2

¿Cuál es su razón para excluir todas las dependencias transitivas?

Si hay un artefacto en particular (como el registro común) que necesita excluir de cada dependencia, el enfoque de la Versión 99 no existe podría ayudar.


Actualización 2012: no use este enfoque. Utilice maven-enforcer-plugin y exclusiones . La versión 99 produce dependencias falsas y el repositorio de la versión 99 está fuera de línea (hay espejos similares, pero tampoco puede confiar en que permanezcan en línea para siempre; es mejor usar solo Maven Central).

Esko Luontola
fuente
1

En un problema similar, tuve la dependencia deseada declarada con el alcance proporcionado. Con este enfoque, las dependencias transitivas se obtienen pero NO se incluyen en la fase del paquete, que es lo que desea. También me gusta esta solución en términos de mantenimiento, porque no hay pom, o pom personalizado como en la solución de Whaley, necesario para mantener; solo necesita proporcionar la dependencia específica en el contenedor y listo

nkr1pt
fuente
-2

Usa el último maven en tu classpath. Eliminará los artefactos duplicados y mantendrá el último artefacto maven.

Samraj
fuente