java maven-2 pom.xml

java - ¿Hay alguna forma de excluir artefactos heredados de un POM padre?



maven-2 pom.xml (7)

Los artefactos de las dependencias se pueden excluir al declarar un elemento <exclusions> dentro de una <dependency> Pero en este caso es necesario excluir un artefacto heredado de un proyecto principal. A continuación se incluye un fragmento del POM en discusión:

<project> <modelVersion>4.0.0</modelVersion> <groupId>test</groupId> <artifactId>jruby</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <artifactId>base</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> </parent> <dependencies> <dependency> <groupId>com.liferay.portal</groupId> <artifactId>ALL-DEPS</artifactId> <version>1.0</version> <scope>provided</scope> <type>pom</type> </dependency> </dependencies> </project>

artefacto base , depende de javax.mail:mail-1.4.jar , y ALL-DEPS depende de otra versión de la misma biblioteca. Debido al hecho de que mail.jar de ALL-DEPS existe en el entorno de ejecución, aunque no se haya exportado, colisiona con mail.jar que existe en el elemento primario, que tiene un ámbito de compile .

Una solución podría ser deshacerse de mail.jar del POM padre, pero la mayoría de los proyectos que heredan base lo necesitan (al igual que una dependencia de transtive para log4j). Entonces, lo que me gustaría hacer es simplemente excluir la biblioteca de los padres del proyecto hijo , ya que podría hacerse si la base fuera una dependencia y no el padre principal:

... <dependency> <artifactId>base</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> <type>pom<type> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> </exclusions> </dependency> ...


No use un pom padre

Esto puede sonar extremo, pero del mismo modo el "infierno hereditario" es una razón por la que algunas personas le dan la espalda a la Programación Orientada a Objetos, o de la misma manera que los cirujanos lo mantienen vivo con cirugía de derivación coronaria: elimine el bloque problemático <parent> y copie y pegue cualesquiera <dependencies> que necesite.

Se debe ignorar la suposición de que la división de poms en padres e hijos para "reutilizar" y "evitar el redunancy" debe ignorarse y debe atender sus necesidades inmediatas primero. La redundancia tiene sus ventajas, a saber, la independencia de las complicaciones externas.

Esto es más fácil de lo que parece si generas el pom efectivo (eclipse lo proporciona pero puedes generarlo desde la línea de comando).

Ejemplo

Quiero usar logback pero mi padre pom usa log4j y no quiero ir y tengo que presionar la dependencia de otros niños en log4j hacia abajo en sus propios archivos pom.xml para que el mío no tenga obstrucciones.

Puede obtener mucho de un padre, pero a veces su padre no sabe lo que es bueno para usted.


¿Has intentado declarar explícitamente la versión de mail.jar que quieres? La resolución de dependencia de Maven debería usar esto para la resolución de dependencia sobre todas las demás versiones.

<project> <modelVersion>4.0.0</modelVersion> <groupId>test</groupId> <artifactId>jruby</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <artifactId>base</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> </parent> <dependencies> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>VERSION-#</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.liferay.portal</groupId> <artifactId>ALL-DEPS</artifactId> <version>1.0</version> <scope>provided</scope> <type>pom</type> </dependency> </dependencies> </project>


Algunas ideas:

  1. Tal vez simplemente no podría heredar del padre en ese caso (y declarar una dependencia en base con la exclusión). No es útil si tienes muchas cosas en el pom padre.

  2. Otra cosa para probar sería declarar el artefacto de mail con la versión requerida por ALL-DEPS bajo la ALL-DEPS dependencyManagement en el pom padre para forzar la convergencia (aunque no estoy seguro de que esto resuelva el problema del alcance).

<dependencyManagement> <dependencies> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>???</version><!-- put the "right" version here --> </dependency> </dependencies> </dependencyManagement>

  1. O podría excluir la dependencia del mail de log4j si no está utilizando las funciones que dependen de él (y esto es lo que yo haría):

<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.15</version> <scope>provided</scope> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> </exclusions> </dependency>

  1. O puede volver a la versión 1.2.14 de log4j en lugar de la versión 1.2.15 hereje (¿por qué no marcan las dependencias anteriores como opcional ?!).

Cuando llamas a un paquete pero no quieres algunas de sus dependencias, puedes hacer algo como esto (en este caso, no quería que se agregara el log4j anterior porque necesitaba usar el más reciente):

<dependency> <groupId>package</groupId> <artifactId>package-pk</artifactId> <version>${package-pk.version}</version> <exclusions> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </exclusion> </exclusions> </dependency> <!-- LOG4J --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.5</version> </dependency>

Esto funciona para mí ... pero soy bastante nuevo en Java / Maven, así que quizás no sea óptimo.


La mejor apuesta es hacer que las dependencias que no siempre deseas heredar sean transitivas.

Puede hacer esto marcándolos en el pom padre con el alcance provisto.

Si aún desea que el padre administre las versiones de estos productos, puede usar la etiqueta <dependencyManagement> para configurar las versiones que desee sin heredarlas explícitamente o pasar esa herencia a los elementos secundarios.


Puede agrupar sus dependencias dentro de un proyecto diferente con packaging pom como se describe en Sonatypes Best Practices :

<project> <modelVersion>4.0.0</modelVersion> <artifactId>base-dependencies</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency> </dependencies> </project>

y hacer referencia a ellos desde su parent-pom (mire la dependencia <type>pom</type> ):

<project> <modelVersion>4.0.0</modelVersion> <artifactId>base</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> <packaging>pom</packaging> <dependencies> <dependency> <artifactId>base-dependencies</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> <type>pom</type> </dependency> </dependencies> </project>

Su proyecto hijo hereda este parent-pom como antes. Pero ahora, la dependencia de correo puede ser excluida en el proyecto hijo dentro del bloque de dependencyManagement gestión:

<project> <modelVersion>4.0.0</modelVersion> <groupId>test</groupId> <artifactId>jruby</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <artifactId>base</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> </parent> <dependencyManagement> <dependencies> <dependency> <artifactId>base-dependencies</artifactId> <groupId>es.uniovi.innova</groupId> <version>1.0.0</version> <exclusions> <exclusion> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement> </project>


Redefina la dependencia (en el pom hijo) con el sistema de scope apuntando a un jar vacío:

<dependency> <groupId>dependency.coming</groupId> <artifactId>from.parent</artifactId> <version>0</version> <scope>system</scope> <systemPath>${project.basedir}/empty.jar</systemPath> </dependency>

El contenedor puede contener solo un archivo vacío:

touch empty.txt jar cvf empty.txt