Maven - ajpaez/Learning GitHub Wiki

Gestión de dependencias en Maven

El repositorio por defecto es conocido como Maven Central y se encuentra en repo.maven.apache.org y uk.maven.org. Maven descarga los artifacts en nuestro repositorio local.

Usando repositorios

Para usar un nuevo repositorio, necesitamos modificar el fichero settings.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<settings
	xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	xmlns:xsi=

"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=

"http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/

settings-1.0.0.xsd">
	<!—Content removed for brevity-->
	<profiles>
		<profile>
			<id>your_company</id>
			<repositories>
				<repository>
					<id>spring_repo</id>
					<url>http://repo.spring.io/release/</url>
				</repository>
				<repository>
					<id>jboss_repo</id>
					<url>https://repository.jboss.org/</url>
				</repository>
			</repositories>
		</profile>
	</profiles>
	<activeProfiles>
		<activeProfile>your_company</activeProfile>
	</activeProfiles>
	<!—Content removed for brevity-->
</settings>

Nota:

La información referente a los repositorios se puede estableces en el fichero setting.xml o el pom.xml, cada uno tienes sus pros y contras. Establecer esta información en el pom permite que nuestros proyectos sean portables, esto permite descargar un proyecto y construir los sin más configuraciones, el problema que tiene esta opción es que cuando el proyecto sea liberado el fichero pom tendrá hardcodeado esta configuración en el, si en un futuro este cambia de localización los desarrolladores deberán cambiar esto sino no funcionará. Establecer la información de los repositorios en el fichero settings.xml no tiene este problema y proporciona mas flexibilidad, esta propuesta es la recomendada.

Maven determina la localización del repositorio local de acuerdo a las siguientes pautas:

  • Primero consulta el tag localRepository dentro del fichero settings.xml en la carpeta .m2 en el home del usuario
  • Si no existe, consulta dicho tag en el fichero settings dentro de la carpeta conf de la instalación de Maven
  • Si no está presente, Maven usará el valor por defecto para el repositorio local, que es la carpeta .m2 en el home del usuario

Identificación de dependencias

Las dependencias Maven son archivos JAR, WAR, EAR y ZIP. Cada dependencia se identifica de forma univoca usando su group, artifac y version (GAV):

  • groupId: Identifica la organización o grupo que es responsable del proyecto. Ej: org.mockito
  • artifacId: Identifica el artifac que se generará, es el nombre del empaquetado sin la versión. Este debe de ser único dentro de todos los proyectos del mismo groupId. Ej: mockito-core
  • version: Indica el número de versión del proyecto. Ej: 2.24.0
  • type: Indica el paquete donde se generará el proyecto. Ej: JAR,EAR

Dependencias transitivas

A menudo las dependencias declaradas en nuestro pom.xml tienen sus propias dependencias. Estas dependencias se conocen como dependencias transitivas.

Una ventaja que nos ofrece Maven es la gestión de estas dependencias ya que se ocupa automáticamente de ellas y las incluye en su proyecto. Maven utiliza dos técnicas: "Dependency Management" o "nearest definition" para resolver conflictos ente versión. Siempre puede garantizar una versión declarándola explícitamente en el POM de su proyecto. Tenga en cuenta que si dos versiones de dependencia están a la misma profundidad en el árbol de dependencia, la primera declaración será la que se use.

Nearest definition

Dicho de otra forma, Maven extrae la dependencia más cerca en el árbol de dependencias a nuestro proyecto y la usa, esto significa que no necesariamente usará la versión más nueva o la más antigua, sino que usará la versión que encuentre primero decentemente.

Por ejemplo, si las dependencias para A, B y C se definen como A -> B -> C -> D 2.0 y A -> E -> D 1.0, entonces se usará D 1.0 al construir A porque la ruta desde A a D a través de E es más corta. Podría agregar explícitamente una dependencia a D 2.0 en A para forzar el uso de D 2.0.

Con las dependencias transitivas, el gráfico de las bibliotecas incluidas puede crecer rápidamente. Por este motivo, hay características adicionales que limitan las dependencias que se incluyen: Dependencias excluidas: si el proyecto X depende del proyecto Y, y el proyecto Y depende del proyecto Z, el propietario del proyecto X puede excluir explícitamente el proyecto Z como una dependencia, utilizando el elemento "exclusión". El siguiente ejemplo veremos cómo excluir la dependencia hamcrest de nuestra dependencia JUnit

<!—Content removed for brevity-->
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>${junit.version}</version>
	<scope>test</scope>
	<exclusions>
		<exclusion>
			<groupId> org.hamcrest</groupId>
			<artifactId>hamcrest</artifactId>
		</exclusion>
	</exclusions>
</dependency>undefined</dependencies>undefined
<!—Content removed for brevity-->

Dependencias opcionales: si el proyecto Y depende del proyecto Z, el propietario del proyecto Y puede marcar el proyecto Z como una dependencia opcional, utilizando el elemento "opcional". Cuando el proyecto X depende del proyecto Y, X dependerá solo de Y y no de la dependencia opcional Z de Y. El propietario del proyecto X puede entonces agregar explícitamente una dependencia a Z, a su elección. (Puede ser útil pensar en las dependencias opcionales como "excluidas de forma predeterminada").

Dependency Management

Antes de comenzar con esta técnica veremos algunos detalles relaccionado con ella.

¿Qué es Maven BOM?

BOM significa "Bill of Materials". BOM es un tipo especial de POM que se utiliza para controlar las versiones de las dependencias de un proyecto y proporciona un lugar central para definir y actualizar dichas versiones. BOM proporciona flexibilidad para agregar una dependencia a nuestro módulo sin preocuparse por la versión de la que dependeremos. Por ejemplo, puedes importar spring-framework-bom en lasección dependencyManagement para asegurarse de que todas las dependencias de spring (tanto directas como transitivas) estén en la misma versión.

La técnica dependency management es un mecanismo para centralizar la información de las dependencias. Cuando tenemos un conjunto de proyectos que heredan un padre común, podemos poner toda la información de dependencias en un archivo POM compartido llamado BOM.

Un beneficio adicional del uso de BOM es que ya no necesita especificar el atributo en las dependencias normales cuando alguna de ellas dependa de la dependencia delclarada en la seccion dependencyManagement.

A continuación se muestra un ejemplo de cómo escribir un archivo BOM:

<project ...>
	<modelVersion>4.0.0</modelVersion>
	<groupId>baeldung</groupId>
	<artifactId>Baeldung-BOM</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>
	<name>BaelDung-BOM</name>
	<description>parent pom</description>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>test</groupId>
				<artifactId>a</artifactId>
				<version>1.2</version>
			</dependency>
			<dependency>
				<groupId>test</groupId>
				<artifactId>b</artifactId>
				<version>1.0</version>
				<scope>compile</scope>
			</dependency>
			<dependency>
				<groupId>test</groupId>
				<artifactId>c</artifactId>
				<version>1.0</version>
				<scope>compile</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

Un fichero BOM es un archivo POM normal con una sección dependencyManagement donde podemos incluir toda la información y las versiones de un artefact.

La forma mas común de usar un BOM es importarlo en nuestro POM. En proyectos grandes, el enfoque de la herencia no es eficiente porque el proyecto puede heredar solo de un padre principal. Importar es la alternativa, ya que podemos importar tantos ficheros BOM como sea necesario.

¿Cuál es el propósito de un objeto BOM?

La relaciones Maven entre padres e hijos son muy útiles para administrar dependencias de múltiples proyectos en un solo lugar. Sin embargo, los proyectos de Maven solo pueden tener un padre (directo). Por lo tanto, se introdujeron importaciones para la administración de dependencias que permiten usar varios proyectos para administrar sus dependencias. Con un import, puede definir una única dependencia y obtener múltiples dependencias gestionadas. Por lo general, un proyecto BOM tendrá muy pocos tag definidos además de la sección dependencyManagement , y no tendrá ninguna dependencia no relacionada, para evitar que afecte demasiado a su proyecto principal.

Un fichero BOM no es un requisito, no es necesario usarlo. En su lugar, puedes añadirtodas las dependencias administradas en la sección dependencyManagement . BOM, sin embargo, simplifica esto bastante. Al utilizar múltiples listas de materiales, su orden será importante si ambos hacen referencia a una dependencia común.

Scope de una dependencia

Si en nuestro proyecto usamos JUnit, esta dependencia es solo necesaria durante la fase de test, no queremos empaquetarla dentro de nuestro archivo final. Otro caso puede ser el driver de conexión con BBDD, solo es necesario cuando la aplicación esté ejecutándose. Maven usa el concepto de scope para permitirnos especificar cuando y donde necesitamos una dependencia.

Podemos encontrar seis scope:

  • compile: Con este scope una dependencia está disponible en el class path en todas las fases del proyecto, construcción, test y ejecución. Es el scope por defecto.

  • provided: Con este scope una dependencia está disponible durante la construcción y ejecución. No se empaquetarán en nuestro artifact. Ejemplo de esto pueden ser las dependencias que se encuentran dentro de nuestro servidor de aplicaciones como Servlet o JSP.

  • runtime: Con este scope una dependencia no está disponible en el class path durante la construcción. En su lugar, se incluyen en el artifact generado y están disponibles en tiempo de ejecución.

  • test: Dependencias con este scope solo están disponibles durante la fase de test. JUnit es un caso de estos.

  • system: Este scope es similar a provided, excepto por que estas dependencias no son recuperadas del repositorio. Su ruta es hardcodeada a su ruta en sistema.

  • import: Este scope solo es compatible con una dependencia de tipo pom en la sección dependencyManagement. Indica la dependencia que se debe reemplazar con la lista efectiva de dependencias en la sección dependencyManagement del POM especificada. Este scope está disponible a partir de la versión 2.0.9.

Proyecto Maven Básico

La siguiente estructura muestra un proyecto Maven básico:

  • maven-hello-world
    • pom.xml
    • src
      • main
        • java
        • resources
      • test
        • java
        • resources
    • target

Cada componente se describe a continuación:

  • maven-hello-world es la carpeta root del proyecto. Típicamente, el nombre del proyecto coincide con el nombre del artifact generado.
  • Carpeta src contiene todo lo necesario para construir el proyecto
  • Carpeta src/main/java contiene el código Java.
  • Carpeta src/test/java contiene los test unitarios Java.
  • La capeta target contiene los artifacts generados, como los .class.
  • El fichero pom.xml se almacena en la carpeta root del proyecto. Otros directorios:
Nombre Descripción
src/main/resources Lugar para almacenar los recursos de nuestra aplicación
src/main/scripts Contiene los scripts usados en la aplicación
src/test/resources Recursos usados durante el stage de test
src/main/webapp Contiene los recursos de la web como ficheros jsp, hojas de estilo e imagenes.
src/it Lugar donde se almacenan los test de integración
src/main/db Lugar donde se almacenan los ficheros de base de datos
src/site Lugar donde almacenar los ficheros usados durante el stage Site. Aquí encontraremos todos los ficheros de configuración de nuestro Site más info

El fichero Pom.xml

Este fichero es el único artifact obligatorio en nuestro proyecto. El siguiente pom es la mínima descripción necesaria:

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mycompany.app</groupId>
	<artifactId>my-app</artifactId>
	<version>1</version>
	<packaging>pom</packaging>
</project>

Se recomienda usar la siguiente convección para versionar nuestro artifact:

<major-version>.<minor-version>.<incremental-version>-qualifier

Properties

En nuestro fichero pom podemos declarar properties que posteriormente serán reutilizadas. El uso más común es establecer en ellas las versiones de nuestras dependencias. El siguiente ejemplo muestra esto mismo con la dependencia JUnit. Es muy utilizado cuando tenemos bastantes dependencias y posteriormente queremos cambiar la versión de alguna de ellas.

<!—Content removed for brevity-->
<properties>
	<junit.version>4.11</junit.version>
</properties>
<!—Content removed for brevity-->
<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>${junit.version}</version>
		<scope>test</scope>
	</dependency>
</dependencies>
<!—Content removed for brevity-->

La sección <properties> puede ser incluida dentro de los distintos perfiles lo que nos permite espficiacar una configuracion con la siguiente expresion: $ {profile.provided.path}.

Profile

Maven está diseñado para crear construcciones portables que trabajn a traves de las difirerentes plataformas y capaces de ejecutarse en distintos enviromnments. Podemos encontrarnos con situaciones donde necesitemos construir el mismo poryecto de forma distinta. Por ejemplo, construiirle para ejecutarse en un entorno de desarrollo o de produccion o construirlo para una plataforma linux o una windows.

Para abordar estas circunstancias, Maven 2.0 introduce el concepto de un perfil de construcción. Los perfiles se especifican utilizando un subconjunto de los elementos disponibles en el propio POM (una sección adicional), y se activan de varias maneras.

Maven proporciona tres tipos de perfil distintos:

  • Por el perfil del proyecto
  • Por el perfil de usuario definido definido en el fichero setting en la carpeta .m2 en el home del usuario
  • Perfil global definido en el fichero de configuracion global, en el disctorio M2_HOME

Al crear diferentes perfiles para diferentes variaciones de la compilación del proyecto, puede usar el mismo archivo pom para crear diferentes compilaciones.

Se debe tener cuidado de asegurarse de que esto no resulte en una compilación no portátil. A continuación se puede ver un ejemplo básico de perfil.

<profiles>
	<profile>
		<id>dev</id>
		<activation>
			<activeByDefault>false</activeByDefault>
		</activation>
	</profile>
</profiles>

*¿Qué áreas de un POM se pueden personalizar para cada tipo de perfil? *

Las partes de un fichero Pom que se pueden modificar con un profile dependen de donde se encuentre dicho profile:

1 - Perfiles especificados en archivos externos:

Estos perfiles se encuentran en el fichero settings.xml o profiles.xml, en el sentido más estricto no son portables. Por lo que los elementos a personalizar aquí son limitados, se podrán modificar las secciones de repositorios, pluginsRepositories y properties.

2 - Perfiles en POMs

Al especificar los perfiles en el pom.xml las opciones a modificar son mayores:

-  <repositories>
-  <pluginRepositories>
-  <dependencies>
-  <plugins>
-  <properties>
-  <modules>
-  <reporting>
-  <dependencyManagement>
-  <distributionManagement>
-  un subconjunto de la sección <build>:
	-  <defaultGoal>
	-  <resources>
	-  <testResources>
	-  <finalName>

Ejecutar maven con un perfil concreto mvn –P dev package

Al ejecutar el comando mvn help:active-profilesla ejecución de maven nos indicará el perfil con el que se ha ejecutado

Maven Life Cycle

Life Cycle and Phases

Maven tiene un ciclo de vida bien conocido cuando está construyendo, en fase de test o generando la distribucion del artifact. Este ciclo de vida está formado por una serie de stages o pasoso que se ejecutan en un mismo orden independientemente del artifact que se esté generando. Estos stages o pasos son conocidos como fasese. Maven tiene tres ciclos de vida: clean, site y default. Cada uno de estos ciclos de vida de compilación se define por listas diferentes de fases de compilación, en la que una fase de compilación representa una etapa en el ciclo de vida.

  • Clean: Este ciclo se encarga de eliminar los ficheros temporales y los artifact generados del directorio target.

  • Site: Este ciclo se encarga de la generación de documentación y la generación del site.

  • Default: Este ciclo se encarga de la compilación, empaquetado y despliegue del proyecto Maven. Esta compuesto de las siguientes fases:

  • validate: Esta fase valida que toda la información está disponible y correcta y que todas las dependencias están descargadas y disponibles.

  • process-resources: Esta fase copia los recursos del proyecto a los paquetes destino.

  • compile: Esta fase compila todo el código fuente.

  • test: Esta fase lanza los test unitarios Este paso no requiere que la aplicación sea generada.

  • package: Esta fase empaqueta el código compilado en su formato de distribución, JAR, WAR, etc.

  • integration-test: Esta fase procesa el paquete en el entorno de integración de test.

  • verify: Esta fase lanza las validaciones para verificar que el paquete es válido.

  • install: Esta fase instala el paquete en el repositorio local.

  • deploy: Esta fase instala el paquete final en el repositorio configurado.

Cada fase se compone de plugin goals. Un plugin goal es una tarea específica que construye el proyecto. Algunos goals solo tienen sentido en fases específicas (por ejemplo, compile goal de Maven Compiler plugin tiene sentido en la fase de compilación, pero checkstyle goal de Maven Checkstyle plugin se puede ejecutar en cualquier fase). Entonces, algunos goals están vinculados a una fase específica de un ciclo de vida, mientras que otros no lo están.

Debido a que el ciclo de vida predeterminado define claramente el orden de las fases, puede generar un artefacto simplemente ejecutando el comando mvn package. Maven ejecutará automáticamente todas las fases antes de la fase solicitada.

El elemento `<packaging />` en el archivo pom.xml asignará automáticamente los objetivos correctos para cada una de las fases sin ninguna configuración adicional. Recuerde que esto es un beneficio de CoC. Si el elemento de empaquetado contiene el valor jar, entonces la fase del paquete estará vinculada a jar goal en jar plug-in. Del mismo modo, para un artefacto WAR, pom.xml vinculará el paquete a un war goal en el war plug-in.

Algunas fases que no son llamadas desde la línea de comandos.

Las fases nombradas con palabras (pre- *, post- * o process- *) generalmente no se llaman directamente desde la línea de comando. Estas fases secuencian la compilación, produciendo resultados intermedios que no son útiles fuera de la compilación. En el caso de ejecutar integration-test, el entorno puede quedar en un estado pendiente.

Las herramientas de cobertura de código como Jacoco y los complementos de contenedor como Tomcat, Cargo y Docker están vinculados a los objetivos a la fase de prueba de integración previa para preparar el entorno del contenedor de prueba de integración. Estos plugins también vinculan goals en fase post-integration-test para recopilar estadísticas de cobertura o retirar el contenedor de pruebas de integración.

Los plugins de cobertura y Failsafe están vinculados a la fase integration-test y fase de verificación. El resultado son los test y los informes de cobertura disponibles después de la fase de verificación. Si la prueba de integración se llamaba desde la línea de comandos, no se generan informes. Lo peor es que el entorno del contenedor de prueba de integración se deja en un estado de suspensión; El servidor web Tomcat o la instancia de Docker se deja en ejecución, y que Maven ni siquiera puede terminar por sí mismo.

Goals y Plug-ins

Los procesos de generación que generan de artifacts generalmente requieren varios pasos y tareas para completarse con éxito. Los ejemplos de tales tareas incluyen compilar el código fuente, ejecutar una prueba unitaria y empaquetar el artifact. Maven utiliza el concepto de goals para representar tales tareas granulares.

Los objetivos en Maven se empaquetan en plug-ins, que son esencialmente una recopilación de uno o más objetivos. El compiler es el complemento que proporciona goal compile. Ejecutar un goal en la línea de comandos requiere la siguiente sintaxis:

mvn plugin_identifier:goal_identifier

Goal compile

mvn compiler:compile

el parámetro compile indica la invocación del ciclo de vida por defecto en Maven. La fase compile básicamente lanza por si misma el goal compile de Maven Compiler plugin.

Goal clean

mvn clean:clean

Cuando se invoca la fase clean, Maven deduce automáticamente que se invoca el ciclo de vida clean . Utiliza el plugin Maven Clean para esto. El plugin tiene un solo objetivo, llamado clean, limpiar el directorio de trabajo. Como clean es un ciclo de vida separado del ciclo de vida predeterminado (build), se debe llamar explícitamente a clean antes del ciclo de vida predeterminado si necesita asegurarse de que se elimine el directorio de trabajo.

Perform Goal

El goal perform es responsable de verificar el código de la nueva tag creada y construir y despliega el código liberado en el repositorio remoto. Las siguientes fases se ejecutan como parte del goal perform:

  • verify-completed-prepare-phases: Esto valida que una fase de preparación haya sido ejecutada antes de ejecutar perform goal.

  • checkout-project-from-scm: verifica el código liberado desde el tag creado en SCM.

  • run-perform-goal: ejecuta los goals asociados con perform.

Los lug-ins Plug-ins y su comportamiento pueden ser configurados usando la sección plug-in del pom.xml.

Maven Archetypes

Los archetypes de Maven son plantillas de proyectos que permiten a los usuarios generar nuevos proyectos fácilmente.

Los arquetipos de Maven también proporcionan una gran plataforma para compartir buenas prácticas y hacer cumplir la coherencia más allá de la estructura de directorios estándar de Maven.

Para crear un nuevo proyecto basado en un archetype, tú necesitas invocar el goal mvn archetype:generate

Proyectos multimódulo

Los proyectos de Java Enterpise Edition (JEE) a menudo se dividen en varios módulos para facilitar el desarrollo y mantenibilidad. Cada uno de estos módulos produce artefactos como Enterprise JavaBeans (EJBs), servicios web, proyectos web y clientas en jars. Maven permite la creación de múltiples proyectos que se anidan en un solo proyecto de Maven. En Maven podemos crear dos tipos de proyectos multimódulo:

Herencia del proyecto

Maven permite especificar una serie de elementos en el archivo pom principal y estos se fusionarán con el proyecto heredado. estos elementos son:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources Para esto debemos indicar en los pom hijos quien es el padre de estos poms

Módulo 1: pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.

apache.org/xsd/maven-4.0.0.xsd"
	xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.apr.maven-hello-world</groupId>
		<artifactId>maven-hello-world-parent</artifactId>
		<version>1.0.0-SNAPSHOT</version>
	</parent>
	<groupId>com.apr.maven-hello-world</groupId>
	<artifactId>maven-hello-world-web</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>maven-hello-world-web Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>maven-hello-world-web</finalName>
	</build>
</project>

Para que las etiquetas sean sobrescritas en los hijos basta con eliminarlas de los pom hijos.

Agregación de proyecto

Una diferencia clave entre la herencia y la agregación es que, la agregación se define con un enfoque de arriba hacia abajo, mientras que la herencia se define al revés. En Maven, proyecto la agregación es similar a la herencia del proyecto, excepto que el cambio se realiza en el padre pom en lugar de los poms hijo.

Maven utiliza el término módulo para definir un hijo o subproyecto, que forma parte de un proyecto. Un proyecto agregado puede construir todos los módulos juntos. Además, cuando ejecutamos en el archivo pom principal o el archivo pom del proyecto agregado también se aplicará a todos los Módulos que contiene.

Parent pom.xml

<?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/maven4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.apr.maven-hello-world</groupId>
	<artifactId>maven-hello-world-parent</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<packaging>pom</packaging>
	<name>maven-hello-world-parent</name>
	<modules>
		<module>maven-hello-world-web</module>
		<module>maven-hello-world-backend</module>
		<module>maven-hello-world-db</module>
	</modules>
</project>

La etiqueta <module> permite declarar módulos hijos en un proyecto multimodular. A medida que se genera cada módulo, Maven los registra de forma como un módulo hijo.

Además, modifica el archivo pom.xml del módulo individual y agrega la información del pom principal.

En el archivo pom principal, especificamos propiedades y dependencias. Debido a la relación definida, cuando Maven se ejecuta en el proyecto hijo, hereda groupId, versión, propiedades y dependencias definidas en el padre.

Combinando herencia y agregación

Al utilizar herencia de proyectos de Maven, podemos compartir atributos de compilación comunes como propiedades y dependencias en todos los hijos. También podemos agregar módulos y construirlos juntos. Cuando se usa la herencia del proyecto, el padre no está al tanto del hijo. En el caso de agregación, cada módulo no es consciente de la agregación.

Podemos combinarlos y obtener los beneficios de ambos. Para ello basta con combinar los dos métodos vistos anteriormente.

Podemos compilar solo un proyecto hijo, añadiendo un perfil para su compilación:

<profiles>
	<profile>
		<id>dev</id>
		<modules>
			<module>maven-hello-world-web</module>
			<module>maven-hello-world-backend</module>
		</modules>
	</profile>
</profiles>

Documentación e informes

Site Life Cycle

Maven proporciona el site life cycle que puede ser usado para generar la documentación de un proyecto.

mvn site

Cuando finalice la ejecución del comando un site habrá sido generado en la carpeta target del proyecto. Podemos generar este sitio ejecutando también el comando:

mvn clean site

Generando informes Javadoc

Maven incorpora un plugin para generar la documentación Javadoc de nuestro proyecto. Solo necesitamos declarar dicho plugin en la sección de report dentro del fichero pom.xml

<project>
	<!—Content removed for brevity-->
	<reporting>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-javadoc-plugin</artifactId>
				<version>2.10.1</version>
			</plugin>
		</plugins>
	</reporting>
</project>

Tras ejecutar mvn clean siteserá generado el Javadoc, tras la ejecución el apidoc se puede encontrar en el directorio /target/site.

Generando informes de test unitarios

Maven incorpora un plagin para Surefire que proporciona una interfaz para lanzar los test creados bien con JUnit o TestNG. Además, puede mostrar los resultados tanto en XML como en HTML, estos resultados proporcionan al desarrollados un mecanismo de búsqueda de test fallidos rápido. Este plugin es configurado en la sección reporting del fichero pom.xml.

<project>
	<!—Content removed for brevity-->
	<reporting>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-report-plugin</artifactId>
				<version>2.17</version>
			</plugin>
		</plugins>
	</reporting>
</project>

Podemos generar este sitio ejecutando el comando:

mvn clean site

Generando informes de cobertura de código

La cobertura de código es la herramienta que nos informa sobre cuanto código ha sido testeado. Proporciona un indicador de la calidad de nuestros test. Dos herramientas para esto son Emma, JaCoCo y Cobertura.

<project>
	<!—Content removed for brevity-->
	<reporting>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>cobertura-maven-plugin</artifactId>
				<version>2.6</version>
			</plugin>
		</plugins>
	</reporting>
</project>

Generando informes de FindBugs

FindBugs es una herramienta para detectar errores en nuestro código Java. Utiliza un analizador estativo para detectar patrones de bug, bucles infinitos o posibles situaciones de nullpointer.

<project>
	<!—Content removed for brevity-->
	<reporting>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>findbugs-maven-plugin</artifactId>
				<version>3.0.0</version>
			</plugin>
		</plugins>
	</reporting>
</project>

Otras alternativas son PMD o CheckStyle. La primera identifica errores de codificación comunes y la segunda violaciones de guidelines en nuestro código.

Maven Release

Integración con Nexus

Para dicha integración será necesario un elemento de tipo <distributionManagement> en el archivo pom.xml, como el siguiente. Este elemento se utiliza para declarar la ubicación donde se almacenarán los artifats del proyecto cuando este se despliegue. El elemento repository indica la ubicación donde se liberarán los artifacts . De manera similar, el elemento <snapshotRepository> identifica la ubicación donde se almacenarán las versiones SNAPSHOT del proyecto.

<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>
	<!-- Content removed for brevity -->
	<distributionManagement>
		<repository>
			<id>nexusReleases</id>
			<name>Releases</name>
			<url>http://localhost:8081/nexus/content/repositories/releases</url>
		</repository>
		<snapshotRepository>
			<id>nexusSnapshots</id>
			<name>Snapshots</name>
			<url>http://localhost:8081/nexus/content/repositories/

snapshots</url>
		</snapshotRepository>
	</distributionManagement>
	<!-- Content removed for brevity -->
</project>

Como la mayoría de los administradores de repositorios, el despliegue en Nexus es una operación restringida. Serán necesarias las credenciales ubicadas en el fichero settings.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<settings
	xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	xmlns:xsi=

"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=

"http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/

settings-1.0.0.xsd">
	<servers>
		<server>
			<id>nexusReleases</id>
			<username>deployment</username>
			<password>deployment123</password>
		</server>
		<server>
			<id>nexusSnapshots</id>
			<username>deployment</username>
			<password>deployment123</password>
		</server>
	</servers>
</settings>

Para desplegar simplemente ejecuta mvn deploy

Maven trata las versiones de SNAPSHOT de manera diferente a las versiones release.

Para una versión de lanzamiento, Maven comprueba si el artefacto está disponible en el repositorio local que ya está descargado. Si es así, no intenta obtener el mismo de los repositorios remotos.

Para las versiones de SNAPSHOT, incluso si el artefacto está disponible localmente, comprueba las actualizaciones de la versión de SNAPSHOT en el repositorio remoto según la política de actualización que puede ser configurar.

Por defecto, el intervalo de actualización es una vez al día. Esto significa que, si Maven descarga una dependencia de SNAPSHOT al mediodía de hoy, buscará una actualización al mediodía de mañana y no antes de eso, independientemente de cuántas veces construya el proyecto.

El intervalo de actualización se puede especificar en la sección de repositorio del archivo pom o de configuración de la siguiente manera: `<updatePolicy>always<updatePolicy>`

Las opciones son always, daily(default), interval: X (donde X es un número entero en minutos) o never.

Otros comandos interesantes

  • Construir un proyecto: mvn package

  • Maven Tree : mvn dependency:tree

  • Obviar los test: puedes hacerlo usando la siguiente propiedad maven.test.skip , así, mvn package –Dmaven.test.skip=true

  • Maven generate Goal: mvn archetype:generate

  • Detecting unused/undeclared dependencies: mvn dependency:analyze

⚠️ **GitHub.com Fallback** ⚠️