Maven
Maven es una herramienta de automatización de gestión de proyectos independiente del IDE.
Un proyecto Maven se reconoce por tener un fichero pom.xml en la carpeta raíz, que describe qué dependencias necesitamos y cómo se compila la aplicación.
Ejecutar un proyecto Maven
Para ejecutar un proyecto Maven, se ejecuta Maven (ya sea el incluído en el IDE o uno instalado normalmente) en la ruta donde esté el pom.xml con una serie de comandos.
La ejecución maven más común es compilar una aplicación, que suele hacerse con el comando
mvn clean install
Este comando ejecuta Maven, haciendo:
- clean: una limpieza de la carpeta target
- install: ejecuta los tests, y si los pasa compila la aplicación y la instala en el repositorio Maven local.
Crear un proyecto Maven
Podemos crear un proyecto Maven desde el IDE (por ejemplo, en IntelliJ es una opción en el menú “Nuevo proyecto” si tenemos instalado el plugin de Maven); para ello tenemos que especificar los siguientes parámetros:
-
Arquetipo: indica la plantilla de proyecto que se va a usar en vez la plantilla por defecto.
Normalmente no se usa salvo para plugins o módulos de determinados programas.
-
groupId: identificador de la compañía o persona que desarrolla.
Suele seguir la nomenclatura de paquetes Java
pais.nombre, seguido a veces del grupo de proyectos al que pertenece.Por ejemplo, para “danpintas” en España, el groupId normal será
es.danpintas, oes.danpintas.abpjsi hacemos varios proyectos que tienen sentido como conjunto. -
artifactId: nombre del proyecto.
Su formato habitual es palabras en minúsculas separadas por guiones, por ejemplo
proyecto-prueba.El conjunto groupId-artifactId debe ser único.
-
version: versión inicial del proyecto.
El formato habitual son tres números “majorVersion.minorVersion.patchVersion”, por ejemplo
1.0.3.Es común ver que se le añade el sufijo
-SNAPSHOTpara referirse a una versión que está en desarrollo, siendo una release un único commit en el que se sólo se quita el identificador de SNAPSHOT y el siguiente commit el paso a la SNAPSHOT de la siguiente versión (por ejemplo, dos commits en los que la versión pasa de1.0.3-SNAPSHOTa1.0.3y a1.0.4-SNAPSHOT.
Estructura por defecto de un proyecto Maven
- src: ruta de todas las fuentes de la aplicación
- main: subruta para las fuentes utilizadas por el proyecto compilado
- java: código java organizado en paquetes
- resources: otros recursos usados por la aplicación (p.e. ficheros de configuración o imágenes)
- test: ubicación de las fuentes usadas sólo para testing, que no se incluirán en la aplicación compilada.
- java/resources: similares a las subcarpetas de main
- main: subruta para las fuentes utilizadas por el proyecto compilado
- target: ruta objetivo de la compilación del proyecto, donde podrás encontrar la aplicación compilada
- pom.xml
Estructura de un pom.xml
En el xml de ejemplo a continuación encontrarás explicaciones de los distintos elementos que lo componen.
<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- A lo largo del pom se referencian otros proyectos maven como dependencias
Estas se usan con el mismo formato de pom: groupId, artifactId, version
Podemos buscar dependencias para proyectos en mvnrepository.com -->
<!-- Indicar un proyecto padre es opcional, se usa para heredar configuraciones Maven -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<!-- Propiedades usadas al crear el proyecto -->
<!-- En un proyecto con padre puede no indicarse y usará el groupId del padre -->
<groupId>es.danpintas</groupId>
<artifactId>proyecto-prueba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Tipo de aplicación a compilar:
jar: valor por defecto, aplicación autoejecutable
war: aplicación web para ser desplegada en un servidor (por ejemplo Tomcat)
pom: el proyecto sólo tiene configuraciones y no se compila;
se usa principalmente en proyectos padre -->
<packaging>jar</packaging>
<!-- Propiedades para reutilizar en el pom -->
<properties>
<!-- Propiedades por defecto para indicar la versión de Java
La versión de Java que usa por defecto es Java 5
Hasta Java 8 se usa 1.version en vez de sólo la versión -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Propiedades por defecto para indicar la codificación de nuestros ficheros -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.report.outputEncoding>UTF-8</project.report.outputEncoding>
<!-- Propiedad personalizada para la versión de una dependencia -->
<mysql.version>8.0.20</mysql.version>
</properties>
<!-- Gestión de versiones de dependencias
Esto es útil especialmente en poms padre cuando no todos los hijos
usan la dependencia pero queremos que todos usen la misma versión -->
<dependencyManagement>
<dependencies>
<!-- Podemos importar un pom aquí
para usar las mismas versiones de todas sus dependencias -->
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>8.8.2</version>
<type>pom</type>
<!-- Necesario cuando importamos un pom en dependencyManagement -->
<scope>import</scope>
</dependency>
<!-- También podemos usar dependencias simples -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.3.3</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Dependencias del proyecto, librerías que necesitamos para nuestro proyecto -->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version> <!-- referencia a una property -->
<scope>runtime</scope>
</dependency>
<!-- Al ir gestionado por un pom en dependencyManagement la versión es opcional -->
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-server</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<!-- Alcance de la dependencia, nos indica cómo se gestiona
para ejecutar y/o compilar la aplicación
- compile: - valor por defecto
- disponible en main y test
- transitiva
- se compila
- test: - solo disponible en test
- no transitiva
- no se compila
- provided: - disponible en main y test
- no transitiva
- no se incluye en la compilación
- se usa principalmente en aplicaciones war
para librerías que incluye el servidor
- runtime: - disponible en main y test
- transitiva
- no se compila (ni es necesaria para compilar)
- usada en implementaciones de librerías comunes,
como drivers de base de datos
* Si una dependencia de un pom es transitiva,
se importa también al importar dicho pom.
Es decir, si A importa a B y B tiene C como dependencia,
A importa también C si la dependencia de C en B es transitiva
con el mismo alcance con el que importa B-->
<scope>test</scope>
</dependency>
</dependencies>
<!-- Configuración de la compilación -->
<build>
<!-- Nombre de la aplicación compilada,
por defecto ${project.artifactId}-${project.version} -->
<finalName>prueba</finalName>
<plugins>
<!-- Aquí se incluyen los plugins necesarios para la compilación -->
</plugins>
</build>
</project>
Ejercicios
Crea un nuevo proyecto Maven que:
- Contenga una clase QuickMaths con un método “add” que acepte dos parámetros y retorne su suma
- Contenga una clase QuickMathsTest que compruebe el comportamiento de QuickMaths
- La aplicación compilada debe incluir la clase QuickMaths pero no la clase QuickMathsTest ni dependencias
Este ejercicio de prueba es simple, pero basta para practicar el uso más común de maven (gestión de dependencias); el resto de conceptos se pondrán en uso como parte de otros proyectos.