Maven

De Dos Ideas.

Maven es una herramienta software para la gestión y comprensión de proyectos Java.

La versión 2 usa un archivo de configuración en XML llamado pom.xml. Su funcionalidad es parecida a Apache Ant de manera que permite compilar, ejecutar test o realizar distribuciones pero con la diferencia que trata de forma automática las dependencias del proyecto. Una de las más importantes características es su actualización en línea mediante servidores repositorios. Maven es capaz de descargar nuevas actualizaciones de las bibliotecas de las que depende el proyecto y de igual manera subir una nueva distribución a un repositorio de versiones, dejandola al acceso de todos los usuarios.

Contenido

Diferencias con Ant

Declarativo vs. Procedural

En Ant las acciones a realizar se definen en forma procedural paso por paso, mientras que con Maven se declara que plugins se van a utilizar, con que configuración y con que dependencias y Maven se encarga del orden en el que se utilizan las cosas para lograr el objetivo declarado.

Conceptos de Maven

Dependencias Transitivas (Transitive Dependencies)

Esto es que las dependencias que declara una dependencia son utilizadas como dependencias propias del POM que se está utilizando. Ejemplo: si A declara dependencias sobre B y B declara dependencias sobre X e Y, cuando se ejecuten las fases del ciclo de vida de Maven se van a utilizar como dependencias B, X e Y.

POM (Project Object Model)

Es un archivo xml llamado pom.xml y ubicado en la raiz de un proyecto (o un módulo) que declara datos sobre el mismo, dependencias y plugins a utilizar durante el ciclo de vida de la administración del proyecto. [1]

Herencia y POM Real (Effective POM)

Los POMs pueden heredar de otro POM que se defina como parent. La raiz implícita desde donde heredan todos los POMs es el Super POM definido por Maven. El POM resultante luego de incorporar todos los ancestros se llama Effective POM. Se puede inspeccionar corriendo el goal effective-pom del plugin help parados sobre el directorio donde se encuentra el pom en cuestión.

mvn help:effective-pom

Goal

Los Goals de Maven son las unidades mínimas de ejecución de las que disponemos durante su uso. Los goals pueden programarse en diferentes lenguajes pero en la práctica están la mayoría programados en Java. No es común que como usuario se piense en programar un goal. Un grupo de goals conforman un plugin. La ejecución de un goal se dispara desde línea de comandos invocando Maven con el nombre del plugin que lo contiene:
mvn plugin:goal
. Otra forma de invocar un goal es indirectamente declarando por ejemplo el uso de un plugin en un POM. Maven lo invocará dependiendo de la fase del ciclo de vida cuando por ejemplo se ejecute
mvn compile

Dependencia (Dependency)

Maven maneja todas las necesidades de conseguir artefactos (libs, jars, ears, zips, etc.) mediante las dependencias ubicando cada dependencia mediante las coordenadas.

Grupo (Group)

El grupo es simplemente una forma de agrupar artefactos bajo una denominación común. La identificación del grupo es groupId. El nombre suele ser el nombre de la organización, el projecto o el equipo de trabajo o bien la raiz del package de java que contendrá las clases del artefacto, ej: com.xyz.foo. Lo importante es recordar que el groupId forma parte de las coordenadas de Maven con la que se identifican en forma única los artefactos en las dependencias y los repositorios.

Artefacto (Artifact)

Maven utilza el término artifact para denominar a la unidad mínima que maneja en su repositorio. Puede ser por ejemplo un jar, un ear, un zip, etc. Cuando Maven compila y empaqueta código, produce también artifacts que instala en el repositorio. Los artifacts están agrupados bajo el id de grupo (groupId) y tienen un id propio (artifactId), una versión, un clasificador y una extensión. Para administrar los artefactos en el repositrio Maven los acompaña con un respectivo pom.xml conteniendo los datos anteriores.

Repositorio (Repository)

El_ funcionamiento de Maven se basa en el uso de un repositorio a donde ir a buscar las dependencias. La identificación de los artefactos que necesita se hace a través del sistema de coordenadas groupId:artifactId:version que asegura que cada dependencia sea única y proveer una ruta para conseguirla.

El repositorio por default es el repositorio central de Maven. A este repositorio se suman otros repositorios, un respositorio local y la posiblidad de utilizar un repositorio/proxy.

Cuando Maven sale a buscar y consigue una dependencia la guarda en el repositorio local que es un directorio en la máquina del usuario (~/.m2/repository). Las siguientes veces que necesite esta dependencia irá la conseguirá en el directorio local haciéndolo mucho más rápido que la primera vez.

El directorio central y los directorios de terceros en lo único que se diferencian es en que se va a encontrar en cada uno. En el repositorio central de Maven podemos esperar encontrar la mayoría de las dependencias que necesitemos como JUnit, Maven mismo, Java, Spring, Hibernate, etc.

El repositorio/proxy es un servicio que podemos instalar en la LAN para cumplir una función similar a la del repositorio local pero compartido por un grupo de usuarios. Esto, además de mejorar la performance, permite tener un mayor control de las versiones de dependencias que se utilizarán.

Coordenadas (Coordinates)

Las coordenadas de Maven es la forma de identificar a un projecto, dependencia, plugin o artefacto en forma única en un pom y en un repositorio. Una coordenada se compone de los siguientes identificadores: groupId:artefactId:version.

A veces es necesario generar dos empaquetados distintos de una misma versión por cuestiones técnicas, por ejemplo un mimso artefacto para correr sobre dos entornos diferentes. En esta situación se puede utilizar un identificador más: groupId:artefactId:version:classifier.

Al momento de producir artefactos, estos cuatro identificadores funcionan en conjunto con uno más, pero que no forma parte de la coordenada: packaging y que se refiere al tipo de empaquetado del artefacto (ejs: zip, jar, ear). De hecho no es posible tener en el repositorio dos artefactos de la misma versión pero con diferente empaquetado.

  • groupId nombre bajo el que se agrupan una serie de artefactos (ej: junit, spring, org.xyx, com.tm.projectox').
  • artifactId identificacion de la unidad mínima administrada por el repositorio (ej: junit, moduloEjb, ejb-api, servlet-api).
  • version la versión del artefacto con la siguiente nomenclatura <major version>.<minor version>.<incremental version>-<qualifier>.
  • classifier clasificador que permite diferenciar iguales versiones pero preparadas o compiladas para diferentes entornos.
  • packaging no forma parte de la coordenada y sólo se utiliza al momento de generar un artefacto. Define el formato del empaquetado (ejs: jar, war, zip, pom).

MOJO (Maven Plain Old Java Object)

MOJO es el término que utiliza Maven para referirse a un artefacto que representa un Goal. El término parte de un juego de palabras entre POJO (Plain Old Java Object, clases simples sin imposiciones de un framework) y Mojo (un hechizo mágico que se hace típicamente envolviendo ciertos elementos en un paño rojo). Maven hacen al término MOJO extensivo también a goals programados en otros lenguajes.

Para programar un Goal utilizando Java como lenguaje, basta con escribir una clase que haga lo que se necesita hacer con la única imposición de implementar una interfase. El resto de la configuración va en un descriptor en xml. Luego solo resta empaquetarlo con la ayuda del propio Maven y publicarlo en algún repositorio.

Plugin

Un Plugin es un conjunto de Mojos (Goals) junto con una descripción y configuración en un xml. Los plugins pueden instalarse y distribuirse mediante los repositorios. Los goals de los plugins pueden utilizarse desde línea de comando: mvn plugin:goal o declarándolo en el pom en la sección <plugins/> con el tag <plugin//>.

Ciclo de Vida (Lifecycle)

Maven utiliza el concepto de cilcos de vida para ejecutar una secuencia ordenada de pasos denominados fases. El ciclo de vida más común y el usado por defecto por Maven es el de build.

Este ciclo de vida define la secuencia de fases que va desde validar la integridad hasta el despliegue en su instalación final de un proyecto. Cuando se solicita la ejecución de una fase Maven ejecuta primero todas las fases anteriores siguiendo la secuencia y termina en la fase solicitada.

Cuando la ejecución llega a una determinada fase, Maven busca los plugins que estén adjuntados a la misma y ejecuta los goals correspondientes. Pueden existir ninguno o más plugins asociados a una fase.

Las fases en sí sólo definen un concepto en forma vaga y no ejecutan código sino que son anclajes para adjuntar los goals de los plugins para que se ejecuten en el momento apropiado.

Para pedirle a Maven que ejecute los goals asociados hasta un determinado punto en el ciclo de vida se ejecuta mvn phase donde phase es alguna de las fases del ciclo de vida en cuestión, por ejemplo mvn package ejecutará la secuencia de phases desde testing, pasando por compilación y terminando en el empaquetado de los artefactos. En esta secuencia pasa por una veintena de fases.

Arquetipo (Archetype)

La descripción y administración de un proyecto con Maven requiere que el proyecto tenga una estructura determinada y que tenga los pom.xml correspondientes. Existe un plugin en Maven que permite generar la estructura y configuración inicial de un proyecto a partir de una plantilla. Estas plantillas con llamadas archetypes (arquetipos) y el plugin que permite la generación a partir de los arquitipos se llama también archetype.

Un arquetipo consta de un directorio resources que contiene todos los archivos y directorios que contendrá el proyecto generado y un descriptor en xml.

Los arquetipos pueden publicarse en un repositorio al igual que cualquier otro artefacto.

Perfiles (Profiles)

Maven está diseñado para maximizar la portabilidad de los artefactos. Es posible redefinir prácticamente cualquier parte de un POM definiendo un perfil. Pueden definirse varios perfiles. La activación de un perfil puede dispararse por uno o una combinación de las siguientes evaluaciones:

  • Existencia o inexistencia de un archivo
  • Sistema operativo
  • Variables de entorno del sistema operativo
  • Inexistencia de variables de entorno del sistema operativo

Para más información, ver Perfiles en Maven

Propiedades (Properties)

Las propiedades son valores que pueden ser accedidos en cualquier lugar del pom donde se espera un valor envolviendo la propiedad en ${}, ej: ${project.groupId}. Existen algunas propiedades preestablecidas:

  • ${project.*} para acceder a cualquier valor definido en el POM
  • ${parent.*} para acceder a los valores de un POM ancestro
  • ${settings.*} para acceder a valores definidos en ~/.m2/settings.xml
  • ${env.*} variables de entorno
  • ${x.y.z} para acceder a valores que desde Java se acceden con System.getProperty("x.y.z")
  • ${x.y.z} para acceder a propiedades declaradas en el POM por el usuario en forma <properties><x.y.z>value</x.y.z></properties>

Properties en Maven2[[2]]

Documentación

Maven puede generar un sitio con toda la documentación del proyecto, en la que se incluyen la información básica del proyecto y las dependencias del proyecto, además permite la integración con herramientas de Integración Continua, Gestión de problemas, listas de correo asi como la utilización de reportes personalizados mediante la configuración de plugins. Entre esos reportes personalizados se puede incluir:

  • Resultado de pruebas unitarias
  • Reportes de Checkstyle
  • Reportes de PMD
  • Reportes de Cobertura
  • Reportes de Macker

Para crear dicho site hay que utilizar la siguiente sentencia

 mvn site

Nota: para los proyectos multimódulo hay un bug conocido que por no genera correctamente los hipervinculos a la documentación de los submodulos. Sin embargo, existe el siguiente workaround

 mvn site:stage -DstagingDirectory=<directorio destino>

Snippets

POM Mínimo

Este es el mínimo posible POM. Verifica, testea, compila y empaqueta un proyecto Java.

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.blah.foo</groupId>
<artifactId>foobar</artifactId>
<version>1</version>
</project>

JUnit

Para que se utilice JUnit durante los tests:

<dependencies>
...
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
...
</dependencies>

Módulos

Para crear un proyecto con varios módulos es necesario crear un módulo a modo de raíz de los otros módulos que se quieren agrupar. Cada módulo, incluyendo el raíz, deben tener su propio POM.

Módulo raíz:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fooBar</groupId>
<version>1.0</version>
<artifactId>fooBar</artifactId>
<packaging>pom</packaging>
<name>project</name>
 
<modules>
<module>fooModule</module>
</modules>
 
...
 
</project>

Cualquier otro módulo agrupado por el módulo raíz:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fooBar</groupId>
<artifactId>fooModule</artifactId>
<packaging>war</packaging>
<name>Foo Module</name>
 
<parent>
<groupId>fooBar</groupId>
<artifactId>fooBar</artifactId>
<version>1.0</version>
</parent>
 
...
 
</project>

La estructura de los directorios debe ser la siguiente

+ fooBar
|
|-- pom.xml
|
'-- + fooModule
|
'-- pom.xml

Cambiando la versión del compilador

Para especificar la versión de código fuente y la versión del bytecode generado:

<project>
...
<build>
...
<plugins>
...
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
</project>

EJB

servlets

Plugins útiles

help

help [3] es un plugin con 8 goals que asisten durante el uso de Maven:

  • active-profiles
  • all-profiles
  • describe
  • effective-pom
  • effective-settings
  • evaluate
  • expressions
  • system

help:active-profiles

Lista los perfiles que se incluirán evaluando cuáles están activos de la misma manera que se evaluarán al momento de ejecutar alguno de los comandos de ciclo de vida.

mvn help:active-profiles

help:all-profiles

Lista los perfiles disponibles en el proyecto.

mvn help:all-profiles

help:describe

Describe un plugin o un MOJO.

mvn help:describe

help:effective-pom

Muestra el POM que se va a usar después de combinarlo con los defaults de Maven, unificar en el caso de múltiples POMs y seleccionando los perfiles que van a utilizarse.

mvn help:effective-pom

help:effective-settings

Muestra los settings que realmente van a utilizarse

mvn help:effective-settings

archetype

install

Plugins

  • Jar
  • War
  • Ear
  • JUnit
  • Distribution: permite meter en un fichero zip todos los archivos del proyecto
  • PDF: genera la documentación del proyecto en PDF
  • Checkstyle: control de convenciones de codificación Java
  • PMD: verificación de reglas de codificación

Ver también