¿Cómo estructurar un proyecto de varios módulos de Maven para compilarlo a la vez?
maven-3 (1)
Tengo un proyecto de Maven con múltiples módulos y submódulos y quiero compilarlo a la vez, es decir, usar solo una llamada para "instalar mvn clean".
Para un proyecto básico, la siguiente estructura funcionaría:
.
├── modules
│ ├── moduleA
│ │ └── pom.xml <--- Module A POM
│ ├── moduleB
│ │ └── pom.xml <--- Module B POM
│ └── pom.xml <--- Super POM (at the root of "modules" folder)
└── pom.xml <--- Aggregator POM
Con el agregador siendo:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>aggregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>modules</module>
<module>modules/moduleA</module>
<module>modules/moduleB</module>
</modules>
</project>
El Super POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Módulo A''s POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>moduleA</artifactId>
<parent>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
El módulo B es similar.
Cuando se encuentra en la raíz del proyecto, ejecutar el comando "mvn clean install" (después de limpiar la carpeta .m2 / repository):
[...]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] super-pom .......................................... SUCCESS [ 0.450 s]
[INFO] moduleA ............................................ SUCCESS [ 1.746 s]
[INFO] moduleB ............................................ SUCCESS [ 0.029 s]
[INFO] agregator .......................................... SUCCESS [ 0.006 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
Ahora, si quiero algo que sea más complejo (pero que todavía use un súper POM), como:
.
├── modules
│ ├── lib1
│ │ ├── moduleA1
│ │ │ └── pom.xml
│ │ ├── moduleB1
│ │ │ └── pom.xml
│ │ └── pom.xml <--- lib1 aggregator POM
│ ├── lib2
│ │ ├── moduleA2
│ │ │ └── pom.xml
│ │ ├── moduleB2
│ │ │ └── pom.xml
│ │ └── pom.xml <--- lib2 aggregator POM
│ └── pom.xml <--- Super POM
└── pom.xml <--- Aggregator POM
Con la raíz POM siendo:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>agregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>modules</module>
<module>modules/lib1</module>
<module>modules/lib2</module>
</modules>
</project>
Lib1 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>lib1-agregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>moduleA1</module>
<module>moduleB1</module>
</modules>
</project>
Y, por ejemplo moduleA1 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>moduleA1</artifactId>
<parent>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
Maven no logra resolver los archivos POM (después de limpiar la carpeta .m2 / repository):
[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[WARNING] ''parent.relativePath'' of POM org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13
[WARNING] ''parent.relativePath'' of POM org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13
[WARNING] ''parent.relativePath'' of POM org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13
[WARNING] ''parent.relativePath'' of POM org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13
@
[ERROR] The build could not read 4 projects -> [Help 1]
[ERROR]
[ERROR] The project org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and ''parent.relativePath'' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
Necesito primero construir el super pom:
cd modules/
mvn clean install
Y sólo entonces se compilará:
[INFO] Reactor Summary:
[INFO]
[INFO] super-pom .......................................... SUCCESS [ 0.271 s]
[INFO] moduleA1 ........................................... SUCCESS [ 1.202 s]
[INFO] moduleB1 ........................................... SUCCESS [ 0.027 s]
[INFO] lib1-agregator ..................................... SUCCESS [ 0.006 s]
[INFO] moduleA2 ........................................... SUCCESS [ 0.027 s]
[INFO] moduleB2 ........................................... SUCCESS [ 0.022 s]
[INFO] lib2-agregator ..................................... SUCCESS [ 0.007 s]
[INFO] agregator .......................................... SUCCESS [ 0.007 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
¿Cómo estructuraría el proyecto para que funcione sin esta compilación de dos pasos?
[EDITAR]: como se discutió en los comentarios, agregar la ruta relativa del Super POM a los módulos POM haría que el código se compilara con una línea de comando.
Sin embargo, si quiero distribuir solo lib1 a algunos desarrolladores, a pesar de que mi súper POM está en un repositorio de Maven, lib1 no se compilaría sin toda la estructura del proyecto. Esto hace que el proyecto sea menos modular.
Déjame comenzar como lo hiciste, pero nombro las cosas un poco diferente:
.
├── modules-root
│ ├── moduleA
│ │ └── pom.xml <--- Module A POM
│ ├── moduleB
│ │ └── pom.xml <--- Module B POM
│ └── pom.xml <--- modules root
└── pom.xml <--- project-root
Comencemos con la project-root
del project-root
, que se verá así:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>project-root</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>modules-root</module>
</modules>
</project>
El module parent
se verá así. moduleA
que esto contiene solo la referencia al moduleA
y el moduleA
y moduleB
de la project-root
del project-root
:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>org.test.module</groupId>
<artifactId>modules-root</artifactId>
<packaging>pom</packaging>
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
</project>
moduleA
se verá así. Preste atención a que esto heredará del module-parent
(padre), que es exactamente un nivel por encima de ...
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.test.module</groupId>
<artifactId>module-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>moduleA</artifactId>
<packaging>..</packaging>
<....other dependencies..>
</project>
Si usa este tipo de estructura, simplemente puede ir al nivel de project-root
del project-root
y hacer:
mvn clean install
Además después puedes usar cosas como esta:
mvn -pl moduleA ...
... para construir solo el módulo A (pero permanecer en el nivel de project-root
del project-root
...).
module-parent
puede parecer desperdiciado o superfluo en este ejemplo, pero si obtiene más módulos, puede definir sus dependencias adicionales a través de dependencyManagement
o puede cambiar las configuraciones de complementos a través de pluginManagement
que solo se usarán en esta subárea (móduloA, móduloB, ... .). Si su proyecto se hace más grande, obtendrá más módulos de padres en paralelo ... que contienen diferentes partes de sus aplicaciones ... y diferentes intenciones que pueden lograrse con esta estructura.
Una cosa más es mencionar. He cambiado el groupId
de groupId
de org.test
a org.test.module
en el módulo-padre. Esto a veces es útil si tiene una gran cantidad de módulos, ya que groupId
representa la estructura de carpetas en su repositorio (como hacen los paquetes java en un proyecto Java) ... esto le brinda una mejor visión general ...
La project-root
es la ubicación para definir las dependencias usables en general a través de dependencyManagement
etc ... y los complementos utilizados que deben definirse a través de pluginManagement
... o pueden estar usando maven-enforcer-plugin para definir las reglas generales del proyecto ...
Los escenarios típicos para este tipo de estructura son los proyectos Java EE u otros proyectos grandes (pueden ser con 300 ... o 1000 módulos, sí existen) ...
Si obtiene más módulos, puede usar la capacidad multihilo de maven y construir su proyecto con:
mvn -T 4 clean install
de la project-root
del project-root
que reduce el tiempo de construcción dramáticamente.