Ciclo de vida de construcción de Maven en Java
Aprende los tres ciclos de vida de Maven y las fases principales — validate, compile, test, package, verify, install, deploy — y cómo los objetivos de plugins se vinculan a ellas.
Un ciclo de vida es la idea central de Maven: construir un proyecto no es un conjunto arbitrario de tareas, sino una secuencia ordenada de fases bien definidas. Cuando escribes mvn package, no estás nombrando una acción — le estás pidiendo a Maven que ejecute cada fase hasta package inclusive, en orden. Entender esa secuencia, y cómo los objetivos de los plugins se vinculan a ella, marca la diferencia entre usar comandos a ciegas y saber realmente qué hace tu proceso de construcción.
Tres ciclos de vida, y el que más usarás
Maven incluye tres ciclos de vida integrados. Son independientes — invocar una fase de uno no activa otro.
| Ciclo de vida | Propósito | Fases principales |
|---|---|---|
clean | Eliminar la salida de construcción | pre-clean, clean, post-clean |
default | Construir y desplegar el proyecto | validate … compile … test … package … install … deploy |
site | Generar la documentación del proyecto | pre-site, site, site-deploy |
El ciclo de vida default es donde ocurre el trabajo real. Ese mvn clean install que ves en todas partes es simplemente dos ciclos de vida en un solo comando: la fase clean del ciclo de vida clean, y luego la fase install del ciclo de vida default.
Las fases del ciclo de vida default
El ciclo de vida default tiene 23 fases, pero siete soportan casi toda la carga de cualquier construcción. Siempre se ejecutan en este orden:
| Fase | Qué hace |
|---|---|
validate | Verifica que el proyecto sea correcto y que toda la información necesaria esté disponible |
compile | Compila el código fuente principal del proyecto |
test | Ejecuta pruebas unitarias con un framework adecuado (no requiere empaquetado) |
package | Empaqueta el código compilado en un formato distribuible, por ejemplo un JAR |
verify | Ejecuta comprobaciones sobre los resultados de las pruebas de integración para confirmar la calidad |
install | Copia el paquete en el repositorio local (~/.m2) para otros proyectos locales |
deploy | Sube el paquete a un repositorio remoto para compartirlo |
La regla que lo rige todo: ejecutar una fase ejecuta esa fase y todas las fases anteriores. Por tanto, mvn package ejecuta silenciosamente validate, compile y test primero. No hay forma de "saltarse" fases — solo puedes detenerte antes.
mvn validate # just the sanity checks
mvn compile # validate -> compile
mvn test # validate -> compile -> test
mvn package # ... -> test -> package (produces target/app-1.0.jar)
mvn install # ... -> package -> verify -> install (now in ~/.m2)
mvn deploy # the full pipeline, ending with an uploadLas fases están vacías hasta que los plugins vinculan objetivos a ellas
Una fase es solo un nombre y una posición en la secuencia — no realiza ningún trabajo por sí misma. El trabajo lo realizan los objetivos de plugins que están vinculados a las fases. Un objetivo se escribe como plugin:goal, por ejemplo compiler:compile. Para un proyecto cuyo <packaging> es jar, Maven proporciona un conjunto de vinculaciones predeterminadas razonables:
| Fase | Objetivo vinculado por defecto |
|---|---|
compile | maven-compiler-plugin:compile |
test | maven-surefire-plugin:test |
package | maven-jar-plugin:jar |
install | maven-install-plugin:install |
deploy | maven-deploy-plugin:deploy |
Puedes añadir tus propias vinculaciones en pom.xml. Aquí el plugin exec se conecta a la fase verify para que se ejecute automáticamente cerca del final de la construcción:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>smoke-test</id>
<phase>verify</phase>
<goals><goal>java</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>También puedes invocar un objetivo directamente, fuera de cualquier fase — mvn compiler:compile ejecuta solo ese objetivo, omitiendo el ciclo de vida por completo. Eso es ocasionalmente útil, pero en el día a día llamas a fases y dejas que se disparen las vinculaciones.
Un ejemplo práctico: simulando el ciclo de vida
Maven en sí no está instalado en este entorno de ejecución, así que modelamos el ciclo de vida en Java puro para hacer concretas sus reglas. El programa lista las fases del ciclo de vida default, registra el plugin:goal vinculado a cada una, luego "ejecuta" mvn install — ejecutando cada fase desde validate hasta install, y demostrando que deploy y clean no se incluyen.
Lo que hay que extraer de la ejecución:
- La salida comienza en
validatey se detiene eninstall— seis fases para un solo comando. Esa es la regla acumulativa en acción:mvn installes la abreviatura de ejecutar todo el prefijo de la secuencia hastainstall, nunca solo la fase nombrada. - Cada fase ejecutada imprimió el
plugin:goalvinculado a ella (compile -> compiler:compile,package -> jar:jar, etc.). Las fases son ranuras; los objetivos son lo que realmente compila, prueba y empaqueta.validateimprimió(no goal bound), mostrando que una fase puede ejecutarse sin hacer nada. deploy skipped : trueconfirma que las fases posteriores a la que solicitas nunca se ejecutan. Para publicar en un repositorio remoto debes pedir explícitamentemvn deploy; un simpleinstallpermanece deliberadamente local.clean ran : falsedemuestra quecleanpertenece a un ciclo de vida separado. Invocarinstallno eliminatarget/, por esomvn clean installespecifica los dos — una fase de cada ciclo de vida.- Las fases se ejecutaron en el orden fijo
validate, compile, test, package, verify, instally el programa terminó conBUILD SUCCESS. El orden no es negociable; la promesa de convención-sobre-configuración de Maven se basa en esta secuencia garantizada y repetible.
Comandos habituales en la práctica
Un puñado de invocaciones cubre casi todo el trabajo diario:
mvn clean # delete target/
mvn test # build and run unit tests
mvn package -DskipTests # build the JAR without running tests
mvn clean install # fresh build, install to local ~/.m2
mvn clean verify # CI's favourite: build + unit + integration checks-DskipTests compila las pruebas pero no las ejecuta; -Dmaven.test.skip=true omite también su compilación. Recurre al primero cuando las pruebas son lentas pero deben seguir compilando, y al segundo solo cuando realmente quieras que queden fuera por completo.
Qué hacer a continuación
- ¿Eres nuevo en la herramienta? Empieza con la introducción a Maven, luego lee cómo el POM declara plugins y vinculaciones.
- Las fases como
compileypackagesolo tienen éxito una vez que se resuelven las bibliotecas del proyecto — consulta gestión de dependencias. - ¿Prefieres un modelo de grafo de tareas en lugar de una secuencia de fases fija? Compara con la introducción a Gradle.