exclude - maven-resources-plugin example
Defina complementos de Maven en pom principal, pero solo invoque complementos en proyectos secundarios (4)
Tengo un conjunto de proyectos que todos necesitan ejecutar la misma serie de ejecuciones de complementos de Maven durante sus compilaciones. Me gustaría evitar volver a declarar toda esta configuración en cada proyecto, así que hice que todos heredaran de un proyecto de "plantilla" pom principal que solo contiene esas ejecuciones de plugin (8 mojos diferentes). Pero quiero que esas ejecuciones de complementos solo se ejecuten en los proyectos secundarios y no en el proyecto principal durante las compilaciones de Maven.
He intentado lograr esto de cuatro maneras diferentes, cada una con un efecto secundario que no me gusta.
Declare las ejecuciones de complementos en el elemento de
build/plugins
del pom principal y use properties-maven-plugin para activar las propiedades deskip
en otros complementos en el proyecto principal. Esto no funcionó porque uno de los objetivos del complemento (maven-dependency-plugin: build-classpath) no tiene una propiedad deskip
.Declare las ejecuciones del complemento en el elemento
build/pluginManagement
del pombuild/pluginManagement
. Desafortunadamente, esto requiere que vuelva a declarar cada uno de los ocho complementos en el elemento debuild/plugins
del pom de cada proyecto secundario como:<plugin> <artifactId>maven-assembly-plugin</artifactId> </plugin> ...
Esto es demasiado repetitivo y problemático si alguna vez necesito cambiar los complementos en la plantilla pom.
Declare las ejecuciones de complementos en un perfil en el pom principal que se activa por la falta de un archivo
nobuild.txt
(que existe en el pom principal, por lo que los complementos no se ejecutan allí):<profiles> <profile> <activation> <file> <missing>nobuild.txt</missing> </file> </activation> <build> .... </build> </profile> </profiles>
Esto funciona en su mayor parte, excepto que la ruta del archivo en el elemento
missing
parece estar basada en el directorio de trabajo actual en lugar del proyecto basedir. Esto rompe algunas de las compilaciones de varios módulos que me gustaría poder hacer. Edición: para aclarar, el proyecto de "plantilla" principal es en realidad un módulo en un proyecto multimodular, y la compilación se rompe cuando intento, por ejemplo, hacer unamvn install
en la raíz. La estructura del proyecto se ve así:+ job |- job-core |- job-template |- job1 inherits from job-template |- job2 inherits from job-template
Configurar un ciclo de vida personalizado y el embalaje. Esto parece permitirme vincular los complementos a las fases del ciclo de vida, pero no especificar ninguna configuración .
Entonces, ¿hay otra manera de especificar un grupo de ejecuciones de complementos de Maven que puedan reutilizarse en varios proyectos (con una mínima repetición en cada uno de los poms de esos proyectos)?
Aquí hay otra opción que descubrí here mientras buscaba una solución al mismo problema. Lo estoy publicando aquí porque ya es una buena colección de opciones, con la esperanza de que pueda ayudar a otros a no gastar horas en resolver este problema:
Dado que el complemento tiene la opción de omitir la ejecución, esa opción podría activarse en el pom principal (sección), con el indicador "heredar" establecido en falso para que no se propague a los secundarios:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<inherited>true</inherited>
<configuration>
...
</configuration>
</execution>
</executions>
<!-- Skip plugin execution for parent pom but enable it for all children -->
<configuration>
<skipAssembly>true</skipAssembly>
</configuration>
<inherited>false</inherited>
</plugin>
Aunque era bastante escéptico acerca de esta solución cuando la leí por primera vez, funcionó para mí, al menos para el complemento de ensamblaje.
Personalmente, buscaría la solución 2. La repetición es mínima y, si es posible, debe intentar evitar los perfiles para evitar tener que comenzar a documentar qué perfiles deben activarse para qué proyectos.
Un proyecto debe poder construirse correctamente simplemente haciendo una instalación mvn (clean) install
.
Terminé escribiendo mi propio plugin que utiliza mojo-executor para invocar otros mojos. Esto me permite 1) centralizar la configuración de compilación y 2) minimizar la cantidad de configuración que se duplica en cada uno de los proyectos secundarios.
(En caso de que tenga curiosidad sobre el motivo de todo esto: cada proyecto secundario es un trabajo que se ejecutará desde la línea de comandos. La compilación configura un script de invocador de shell y lo adjunta a la compilación para que se verifique en nuestro artefacto Repositorio. Una secuencia de comandos de implementación más tarde los despliega en la máquina en la que se ejecutarán.)
Partes relevantes de la plantilla del proyecto pom:
<project ...>
<parent> ... </parent>
<artifactId>job-template</artifactId>
<packaging>pom</packaging>
<name>job project template</name>
<build>
<pluginManagement>
<plugin>
<groupId>...</groupId>
<artifactId>job-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-sources-step</id>
<goals><goal>job-generate-sources</goal></goals>
</execution>
<execution>
<id>package-step</id>
<goals><goal>job-package</goal></goals>
</execution>
... (a couple more executions) ...
</executions>
</plugin>
</pluginManagement>
</build>
</project>
Tenía que crear un nuevo proyecto de plugin de maven (job-maven-plugin). Pom se parece a:
<project ...>
<parent> ... </parent>
<artifactId>job-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>job maven executor plugin</name>
<dependencies>
<dependency>
<groupId>org.twdata.maven</groupId>
<artifactId>mojo-executor</artifactId>
<!-- version 1.5 supports Maven 2, while version 2.0 only supports Maven 3 -->
<version>1.5</version>
</dependency>
</dependencies>
</project>
Como puede ver en el proyecto de la plantilla, había varios mojos en mi complemento (uno por fase que necesitaba que ocurriera algo). Como ejemplo, el paquete de trabajo mojo está vinculado a la fase del paquete y utiliza la biblioteca mojo-executor para ejecutar otros dos mojos (que solo adjuntan algunos artefactos de compilación):
/**
* @goal job-package
* @phase package
*/
public class PackageMojo extends AbstractMojo {
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* @parameter expression="${session}"
* @required
* @readonly
*/
protected MavenSession session;
/**
* @component
* @required
*/
protected PluginManager pluginManager;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
ExecutionEnvironment environment = executionEnvironment(project, session, pluginManager);
// Attach script as a build artifact
executeMojo(
plugin(
groupId("org.codehaus.mojo"),
artifactId("build-helper-maven-plugin"),
version("1.7")
),
goal("attach-artifact"),
configuration(
element("artifacts",
element("artifact",
element("file", "${project.build.directory}/script.shl"),
element("type", "shl")
)
)
),
environment
);
// Zip up the jar and script as another build artifact
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-assembly-plugin"),
version("2.3")
),
goal("single"),
configuration(
element("descriptors",
element("descriptor", "${project.build.directory}/job/descriptor.xml")
)
),
environment
);
}
}
Luego, en los proyectos secundarios, solo tengo que referirme al plugin una vez. En mi opinión, esto es mucho más preferible que repetir cada uno de los complementos detrás de escena en cada proyecto secundario (lo que aumenta de forma inaceptable el acoplamiento entre poms). Si quiero agregar una ejecución mojo al procedimiento de compilación en el futuro, solo tengo que modificar un lugar y eliminar un número de versión. El pom del proyecto infantil se ve así:
<project ...>
<parent>
<groupId> ... </groupId>
<artifactId>job-template</artifactId>
<version> ... </version>
<relativePath>../job-template</relativePath>
</parent>
<artifactId>job-testjob</artifactId>
<name>test job</name>
<build>
<plugins>
<plugin>
<groupId> ... </groupId>
<artifactId>job-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Además, la estructura de directorios multimódulo completa ahora se ve así:
+- job
+- job-core
+- job-maven-plugin
+- job-template
+- job-testjob1 (inherits from job-template)
+- job-testjob2 (inherits from job-template)
En mi opinión, esta solución no es del todo óptima, ya que ahora tengo la configuración de complementos incrustada en una serie de mojos en lugar de un pom, pero cumple con mis objetivos para centralizar la configuración y minimizar la duplicación entre los poms de proyectos secundarios.
(Una última nota: acabo de descubrir maven-aggregate-plugin que parece permitir agrupar múltiples ejecuciones de complementos en el pom. Esto podría haber resuelto el problema de una manera un poco más deseable, pero no estoy de humor para rehacer el último Unas pocas horas de trabajo. Aunque podría ser beneficioso para otra persona.)
Una opción más: en lugar de usar una propiedad "omitir", puede cambiar la fase en la que una ejecución está vinculada a un valor inexistente como never
.
Esto funciona muy bien junto con el enfoque <inherited>false</inherited>
sugerido por @Timi