Maven y ciclo de build
Ya tenemos una estructura reconocible, pero compilar cada .java a mano exige recordar rutas, orden y opciones. Si otra persona clona el proyecto, necesita un procedimiento conocido que produzca el mismo resultado y falle de forma visible cuando algo no funciona.
Maven resuelve ese problema describiendo el proyecto en pom.xml y ofreciendo un ciclo de build común. Maven no sustituye a Java: coordina herramientas y tareas para validar, compilar, probar y empaquetar el proyecto.
Un POM mínimo para Java 17
POM significa Project Object Model. Este archivo real y ejecutable identifica el proyecto, fija Java 17 y evita depender de la codificación de la máquina:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>es.skilly</groupId>
<artifactId>gestor-tareas</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
</project>
Las coordenadas distinguen este artefacto de los demás:
groupId: organización o espacio propietario, aquíes.skilly;artifactId: nombre técnico del proyecto,gestor-tareas;version: versión concreta que estamos construyendo;packaging: tipo de artefacto, en este caso un JAR.
maven.compiler.release pide al compilador clases y API compatibles con Java 17. Es preferible a combinar source y target, porque también limita la API disponible. La versión del plugin queda fijada para que el build no cambie por seleccionar otro plugin implícitamente.
Lifecycles, fases y goals
Un lifecycle es una secuencia ordenada. El lifecycle principal, llamado default, contiene fases como:
validate: comprueba que el proyecto puede procesarse;compile: compila producción;test: ejecuta los tests;package: crea el artefacto, por ejemplo el JAR;verify: ejecuta las comprobaciones previstas hasta esa fase.
Al pedir una fase, Maven ejecuta también las anteriores necesarias del mismo lifecycle. Por eso:
mvn package
no se limita a crear un JAR: antes valida, compila y ejecuta los tests.
clean pertenece a un lifecycle separado. Elimina la salida anterior del proyecto; no forma parte del lifecycle default:
mvn clean
Podemos encadenar ambos lifecycles:
mvn clean verify
Primero elimina target/ y después recorre el lifecycle principal hasta verify.
Una fase expresa un punto del ciclo, como compile. Un plugin aporta tareas concretas y un goal es una de esas tareas. Maven enlaza goals de plugins con las fases según el tipo de proyecto. No necesitamos memorizar todos esos enlaces para usar el flujo habitual.
Recorrer el build
Desde la raíz, donde está pom.xml, podemos observar cada paso:
mvn validate
mvn compile
mvn test
mvn package
mvn verify
mvn clean
mvn clean verify
Después de compilar aparece target/classes. Tras package obtenemos:
target/gestor-tareas-1.0.0.jar
El JAR contiene las clases de producción, pero este POM no declara una clase principal en su manifiesto. Por tanto, no debemos documentarlo como ejecutable mediante java -jar. Crear un artefacto y convertirlo en una aplicación ejecutable son decisiones distintas.
Leer el resultado
Una ejecución correcta termina con:
[INFO] BUILD SUCCESS
Un fallo termina con BUILD FAILURE y un código de salida distinto de cero. Ese código permite que un script detecte el resultado sin interpretar visualmente toda la salida.
En Bash podemos consultarlo justo después:
mvn test
echo $?
El valor 0 significa éxito; otro valor indica fallo. No basta con que aparezcan muchas líneas verdes: debemos comprobar la fase solicitada y el resultado final.
Reproducir desde un checkout limpio
Una comprobación útil evita depender de clases antiguas:
mvn clean verify
Para que sea reproducible, el repositorio debe incluir el código, pom.xml y los recursos necesarios, pero no target/. Tras clonar, otra persona debería poder ejecutar el mismo comando con Java 17 y Maven y obtener el mismo artefacto.
Práctica
Crea src/main/java/es/skilly/tareas/app/Main.java:
package es.skilly.tareas.app;
public class Main {
public static void main(String[] args) {
System.out.println("Gestor preparado");
}
}
Usa el POM anterior y comprueba:
mvn validateacepta el modelo;mvn compilecreatarget/classes;mvn testtiene éxito aunque todavía no haya tests;mvn packagecreatarget/gestor-tareas-1.0.0.jar;mvn verifycompleta el lifecycle;mvn cleaneliminatarget/;mvn clean verifyreconstruye todo desde cero.
Solución razonada
Si los archivos están en la ruta correcta, no hace falta enumerarlos: Maven conoce src/main/java. El nombre del JAR combina artifactId y version. Al ejecutar clean, desaparece porque es un resultado generado, y verify lo reconstruye.
Si Maven muestra BUILD FAILURE, busca el primer mensaje que explique la causa, corrígela y repite desde la fase apropiada. En la próxima unidad añadiremos una necesidad nueva al POM: obtener una biblioteca externa sin copiar JARs manualmente.