java - proyecto - Resolviendo problemas de convergencia de dependencia de Maven
problemas maven eclipse (2)
Si JUnit como artefacto aparece como una dependencia en el ámbito de compilación, se trata de un error de una de sus bibliotecas, aquí: ca.juliusdavies.
JUnit siempre debe estar incluido en el alcance de la prueba. Por lo tanto, no se empaqueta en el archivo .jar, .war o .ear producido, en una compilación exitosa.
En general, no hay daño al excluir las dependencias ya incluidas, como cuando la biblioteca 1 y la biblioteca 2 comparten una dependencia común.
El único problema, por supuesto, que puede ocurrir, es cuando la biblioteca 1 y la biblioteca 2 incluyen diferentes versiones del mismo artefacto dependiente. Esto puede causar errores de tiempo de ejecución cuando las características de la biblioteca han cambiado. Afortunadamente, este no suele ser el caso, a menos que la diferencia en los números de versión sea excelente. En general, es aconsejable incluir la última versión de dependencia y excluir la versión anterior. Esto es la mayor parte del tiempo viable.
De lo contrario, compruebe si hay actualizaciones para las dependencias de primer nivel de su proyecto.
Uso el complemento maven-enforcer para verificar problemas de convergencia de dependencia. Un resultado típico sería:
[WARNING] Rule 1: org.apache.maven.plugins.enforcer.DependencyConvergence failed
with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for junit:junit:3.8.1 paths to dependency are:
+-foo:bar:1.0-SNAPSHOT
+-ca.juliusdavies:not-yet-commons-ssl:0.3.9
+-commons-httpclient:commons-httpclient:3.0
+-junit:junit:3.8.1
and
+-foo:bar:1.0-SNAPSHOT
+-junit:junit:4.11
]
Al ver este mensaje, normalmente lo "resolvería" excluyendo la dependencia transitiva, por ej.
<dependency>
<groupId>ca.juliusdavies</groupId>
<artifactId>not-yet-commons-ssl</artifactId>
<version>0.3.9</version>
<exclusions>
<!-- This artifact links to another artifact which stupidly includes
junit in compile scope -->
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
Me gustaría entender si esto es realmente una solución y los riesgos que implica excluir las bibliotecas de esta manera. Como yo lo veo:
El "arreglo" es normalmente seguro, siempre que elija usar la versión más nueva. Esto se basa en que los autores de la biblioteca mantienen la compatibilidad con versiones anteriores.
Normalmente no hay impacto en la construcción Maven (ya que la definición más cercana gana), sin embargo, al excluir la dependencia, le digo a Maven que sé sobre este problema y, por lo tanto, apaciguo el plugin maven-enforcer.
¿Son correctos mis pensamientos y hay una forma alternativa de manejar este problema? Me interesan las respuestas que se centran en el caso general. Me doy cuenta de que el ejemplo de junit
anterior es un poco extraño.
Todos estamos de acuerdo en que JUnit nunca debe establecerse en otro ámbito que no sea la test
. En términos generales, tampoco creo que exista otra solución que excluir la dependencia no deseada, por lo que todos estamos de acuerdo en que tiene razón al hacerlo.
UN CASO SIMPLE:
Como dice Andreas Krueger, puede haber un riesgo con las versiones (en realidad lo encontré). Digamos que las dependencias del proyecto son las siguientes:
+-foo:bar:1.0-SNAPSHOT
+-group1:projectA:2.0
+-group2:projectB:3.8.1
+-group2:projectB:4.11
Tenga en cuenta que es solo una mera simplificación de su caso. Al ver este árbol de dependencias, excluiría el proyecto de dependencia B dado por projectA:
<dependency>
<groupId>group1</groupId>
<artifactId>projectA</artifactId>
<version>2.0</version>
<exclusions>
<exclusion>
<groupId>group2</groupId>
<artifactId>projectB</artifactId>
</exclusion>
</exclusions>
</dependency>
Después de empaquetar el proyecto con maven, la dependencia restante sería group2-someProjectB-4.11.jar, versión 4.11 y no 3.8.1. Todo estaría bien y el proyecto se ejecutaría sin encontrar ningún problema.
Luego, un tiempo después, digamos que decide actualizar a la próxima versión del proyecto A, versión 3.0, que agrega nuevas características excelentes:
<dependency>
<groupId>group1</groupId>
<artifactId>projectA</artifactId>
<version>3.0</version>
<exclusions>
<exclusion>
<groupId>group2</groupId>
<artifactId>projectB</artifactId>
</exclusion>
</exclusions>
</dependency>
El problema es que aún no sabe que projectA versión 3.0 también ha actualizado su proyecto de dependencia B a la versión 5.0:
+-foo:bar:1.0-SNAPSHOT
+-group1:projectA:3.0
+-group2:projectB:5.0
+-group2:projectB:4.11
En ese caso, la exclusión que habría hecho hace un tiempo excluye projectB versión 5.0.
Sin embargo, projectA versión 3.0 necesita las mejoras del proyecto B versión 5.0 . Debido a la exclusión, después de empaquetar el proyecto con maven, la dependencia restante sería group2-someProjectB-4.11.jar, versión 4.11 y no 5.0. En el momento en que utilice cualquiera de las nuevas funciones de projectA, el programa no se ejecutará correctamente.
¿CUÁL FUE LA SOLUCIÓN?
Encontré este problema en un proyecto Java-EE.
Un equipo desarrolló servicios de base de datos. Lo empacaron como projectA. Cada vez que actualizaban los servicios, también actualizaban un archivo que enumeraba todas sus dependencias actuales y las versiones actuales.
ProjectA era una dependencia del proyecto Java-EE en el que estaba trabajando. Cada vez que el equipo de servicio actualizó ProjectA, también verifiqué las actualizaciones de las versiones.
De hecho, no hay daño al excluir una dependencia. Pero cada vez que actualiza una dependencia donde se ha establecido una exclusión, debe verificar:
- si esta exclusión todavía tiene sentido.
- si necesita actualizar la versión de la dependencia excluida en su propio proyecto.
Creo que las exclusiones maven son como cuchillos de cocina. Es filoso, corta verduras sin ningún esfuerzo, pero requiere cuidado al manipularlo ...