Maven Guía rápida
Este documento no pretende ser una guía completa a Maven, solo una guía rápida para poder
iniciarse en Maven y consecuentemente, continuar por cuenta propia hacia características más
avanzadas.
Que es maven?
Maven es una herramienta open source, mediante la cual podemos administrar ciertas etapas del
ciclo de vida de nuestros proyectos, entre variadas cosas más.
Para darnos un ejemplo, con maven podemos compilar nuestros componentes, deployarlos,
correr nuestros casos de pruebas, etc.
Pero acaso no puedo hacerlo con Ant?
Correcto, gran parte de las cosas que se pueden realizar con Maven, pueden implementarse con
Ant, sin embargo podemos pensar en Ant como una herramienta de más bajo nivel, solo por citar
un breve ejemplo, con maven podemos ejecutar la siguiente instrucción:
mvn clear
Esta simple instrucción elimina los directorios donde tenemos deployado nuestro proyecto, muy
útil por ejemplo cuando queremos deployar desde cero nuestro proyecto nuevamente. En Ant
para implementar esta funcionalidad deberíamos realizar un "task" y después buscar los tareas
Ant necesarias para eliminar ciertos directorios. Así pues, podríamos ver a Maven como una
serie de componentes al estilo Ant, pero que ya se encuentran implementados y lo único que
espera es contar con cierta estructura estándar para realizar las operaciones, además de ciertos
parámetros en algunas ocasiones, esto nos lleva a otro punto importante en Maven, el patrón de
estructura de directorios.
Estructura de patrones: Convención vrs Configuración
Un termino acuñado en boga últimamente es utilizar convención en vez de configuración,
ejemplos como Ruby on Rails, han disparado y demostrado la eficiencia de utilizar estructuras
patronicas, en vez de expresar directamente todo en la meta información, así pues nos basamos
en convenciones esperadas, para realizar diferentes acciones.
Maven no escapa a este movimiento, es así como Maven logra compilar, deployar entre muchas
otras tareas disponibles, sin necesidad de que le indiquemos donde se encuentran nuestros
archivos fuentes, recursos, archivos Web, etc.
Maven asume que nosotros contamos con una estructura como esta, por ejemplo:
${basedir}/src/main/java
${basedir}/src/main/resources
${basedir}/src/test/java
${basedir}/src/test/resources
Estos directorios le indica a Maven, donde encontrar nuestros archivos Java, los diferentes
recursos como archivos de "properties", "xmls", entre otros. La carpeta "test" por su parte le
indica a Maven donde se encuentran los archivos "java" y los "recourses" necesarios para las
pruebas de unidad; por ejemplo nosotros podemos tener cargadas configuraciones y classpaths
diferentes a la hora de ejecutar nuestros casos de pruebas.
Artefactos
Los artefactos en Maven, los podemos ver como un tipo de proyecto o componente, Maven
maneja gran variedad de artefactos y dependiendo del tipo que sea nuestro proyecto actual (el
tipo de artefacto se puede ver como una plantilla que Maven ya tiene lista para utilizarla), la
estructura de carpetas básica mencionada en el punto anterior puede extenderse y la forma en que
se deploya puede resultar diferente, por ejemplo cuando el artefacto es un "web-app",
adicionalmente se nos crea una carpeta en:
${basedir}/src/main/webapp
Donde depositamos todos los recursos Web, incluyendo nuestra carpeta "WEB-INF", de igual
manera para los diferentes artefactos dispondremos de variadas estructuras de carpetas agregadas
a la composición básica, antes mencionada.
Manejo de dependencias y repositorios
Maven proporciona un modulo para el manejo de dependencias, ya veremos mas adelante de que
se trata esto del manejo de dependencias, sin embargo por ahora solo mencionar que Maven tiene
un repositorio donde almacena nuestros componentes o componentes de terceros, por ejemplo
los archivos jar de Struts, los archivos jar de Apache Commons, etc. Por defecto el repositorio es
almacenado en un directorio local, regularmente en ${userprofile}/.m2. En este repositorio como
en todos se almacenan los jar, por artefact id y versión. Adicionalmente resulta importante
mencionar que Maven tiene la posibilidad de utilizar directorios compartidos en una Intranet, por
ejemplo, un servidor local donde se podrían almacenar los componentes de la compañía y
compartirlos, al estilo de Framework o librerías de utilidades.
Maven, además cuenta con un gigantesco repositorio (http://repo1.maven.org/maven2/) expuesto
en Internet de donde bajamos la versiones de los diferentes componentes, regularmente nosotros
podemos indicarle a Maven los repositorios que deseamos utilizar, mas adelante cuando se
explique el manejo de las dependencias, entenderemos de mejor manera, el manejo de los
repositorios.
Proyectos
Como hemos mencionado, Maven maneja los proyectos como artefactos y estructuras patronicas
para los directorios, la forma en como Maven conoce la minima meta información de nuestro
proyecto, es mediante el Project Object Manager (POM), este es un archivo XML, alojado en la
raíz de nuestro directorio de proyecto con el nombre de pom.xml.
Creando nuestro primer proyecto
Para crear nuestro primer proyecto necesitamos indicarle a Maven un "groupId", un "artifactId" y
un paquete Java por defecto. El siguiente ejemplo nos muestra como crear el proyecto,
"primerproyecto", con un paquete por defecto "cr.co.jsanca.mavenexample".
mvn archetype:create -DgroupId=cr.co.jsanca -DartifactId=primerproyecto
-DpackageName=cr.co.jsanca.mavenexample
El "groupId", le indica a Maven el identificador de grupo bajo el cual queremos agrupar nuestros
componentes, una buena práctica es agrupar todos los componentes de nuestro proyecto o
compañía bajo un mismo "groupId". Por ejemplo en un proyecto clásico podríamos tener:
mvn archetype:create -DgroupId=cr.co.jsanca -DartifactId=dao -DpackageName=cr.co.jsanca.dao
mvn archetype:create -DgroupId=cr.co.jsanca -DartifactId=service -DpackageName=cr.co.jsanca.service
mvn archetype:create -DgroupId=cr.co.jsanca -DartifactId=action -DpackageName=cr.co.jsanca.action
Las anteriores líneas indican a Maven crear un proyecto dao, service y action bajo el mismo
grupo y con los paquetes Java cr.co.jsanca --> dao, service, action.
El "artifactId", le indica a Maven el identificador especifico del proyecto dentro del group id, así
pues la llave para localizar un proyecto es el group id y el artifact id, con estos dos datos
podemos bajar alguna de las versiones disponibles.
Después de crear nuestro primer proyecto podemos ir a nuestro espacio de disco y comprobar los
siguientes archivos:
primerproyecto
- pom.xml
- main
- java
- cr/co/jsanca/mavenexample/App.java
- java
- test
- java
- cr/co/jsanca/mavenexample/AppTest.java
- java
Como notarán esta es la estructura minima para crear nuestro proyecto de Maven, en nuestro
caso aun no contamos con archivos de recursos, algo importante de anotar es que dentro del
directorio "java" tanto de main y test, Maven solo espera archivos .java, así que el resto de los
archivos que coloquemos no los va tomar en cuenta a la hora de compilar y deployar, por esa
razón que ocupamos crear la carpeta "resources", igual aquí podes crear paquetes Java que se
verán reflejados cuando deployemos nuestro aplicación.
Construyendo nuestro primer proyecto
Como mencionamos anteriormente, Maven nos va ayudar para controlar nuestro ciclo de vida,
por ejemplo si queremos compilar nuestro proyecto, simplemente debemos ejecutar:
mvn compile
Si vamos a la carpeta donde tenemos nuestro proyecto, nos daremos cuenta que tenemos una
carpeta llamada "target", es en esta carpeta donde se almacenan todos los archivos deployados,
.class, .jar, .war, .ear, entre otras cosas que puede deployar maven.
En el caso de nuestro "primerproyecto", la única carpeta con que contamos es "classes" y
contiene el compilado de la clase App.java.
Entre otras funcionalidades que nos proporciona Maven, tenemos:
mvn test
Esta tarea corre nuestro test, por defecto son unit test, de JUnit sin embargo y muy
probablemente existan formas de utilizar otros frameworks.
mvn clear
Esta tarea limpia (elimina) todo el contenido de la carpeta "target", para realizar un compilado,
empaqueta o deployado desde cero.
mvn package
Esta tarea compila, ejecuta los test y empaqueta nuestro proyecto ya sean en .jar, .war o .ear.
mvn install
Esta tarea compila, ejecuta los test y empaqueta nuestro proyecto y adicionalmente lo instala en
el repositorio, para que pueda ser referido como dependencia, por otros proyectos.
mvn deploy
Esta tarea compila, ejecuta los test y empaqueta nuestro proyecto, adicionalmente lo sube a
nuestro servidor o repositorio (tenemos que indicarlo en el pom) para que el ejecutable pueda ser
compartido para otros desarrolladores, en algunas ocasiones uno redirecciona el contexto del
App Server a lo empaquetado en la carpeta "target" de esta manera nos basta con solo hacer un
"package".
mvn site
Esta simpática tarea, genera un sitio con la documentación del proyecto.
Paseando por nuestro POM
Abrimos nuestro archivo POM.XML, y veremos el siguiente contenido:
<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>
<groupId>cr.co.jsanca</groupId>
<artifactId>primerproyecto</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>primerproyecto</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>
</project>
Esta es la configuración por defecto que tenemos, para el proyecto. Vamos analizarlo a
continuación,
ModelVersion, es la versión de la especificación del modelo Maven.
GroupId, actifactId ya los hemos abordados.
Packaging, indica a Maven la forma en que debe empaquetar el proyecto.
Version, indica la versión del build de nuestro projecto.
Dependencies, esta sección es muy importante pues indica a Maven cuales son las dependencias
principales de nuestra aplicación, como se puede notar lo que estamos declarando es una
dependencia hacia otro proyecto Maven, en nuestro caso al proyecto junit, del grupo junit,
versión 3.8.1. El "scope" es utilizado en algunas ocasiones para denotar si esta la naturaleza de la
dependencia, veamos los posibles valores:
compile, este es el scope por defecto y se utiliza para el proceso de compilación.
provided, este dependencia se incluye en tiempo de compilación, pero se omite a la hora de
empaquetar, pues se asume que el JDK o el Server lo contiene, por ejemplo los jar de server api
en Tomcat.
runtime, indica que esta dependencia no es necesaria para compilación pero si para ejecución, tal es el caso de un Driver de JDBC o cualquier componente que se invocado solo por reflexión.
test, esta dependencia solo es utiliza para compilar y ejecutar los fuentes bajo la carpeta test.
Algo importante a considerar en las dependencias es la transitividad de las misma, con
transitividad queremos decir que si una dependencia a la vez depende de otra y esta de otra, etc,
todas estas dependencias serán agregadas cuando empaquetemos nuestro proyecto (package).
Por ejemplo, si incluimos la librería A, y esta depende de B y C
A -> B, C.
Cuando deployemos nuestra aplicación encontraremos bajo “lib” todas las librerias:
lib
- A
- B
- C
Plugins
Los plugins son un mecanismo mediante el cual escalamos la funcionalidad por defecto que
proporciona maven, un plugin puede ser un componente contenido dentro del mismo Maven o
puede ser un componente de terceros, el cual Maven busca en el momento de utilizarlo y lo baja
localmente para utilizarlo, los plugins sirven para cumplir variadas tareas, tales como; indicar en
que compliance queremos compilar nuestro código (5.0, 6.0, etc), como empaquetas y deployar
nuestras aplicaciones, como limpiar el target, correr aplicaciones de terceros como tareas Ant,
plugins de Hibernate para generar nuestra base de datos, de WebServices, para deployar nuestros
Stubs, etc.
A continuación unos ejemplos de plugins:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
Plugin para indicarle a maven, que tanto el código fuente de nuestra aplicación, así como los
compilados, son Java 5.
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webappDirectory>target/war/survey</webappDirectory>
</configuration>
</plugin>
Este plugin le indica a Maven que el directorio donde debe deployar la aplicación Web, es
"target/war/survey".
De manera identica puedes agregar diferentes tipos de plugins y los mismo son datos por Maven
o los fuentes terceras.
Repositorios
Los repositorios son útiles para indicarle a Maven, de donde debe bajarse los diferentes
artefactos, por ejemplo se pueden indicar servidores de open source, servidores a nivel de
intranet, etc. Los repositorios se pueden indicar de la siguiente manera:
<repositories>
<repository>
<id>repo1</id>
<name>Maven Central Repository</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>java.net</id>
<url>http://download.java.net/maven/2</url>
</repository>
</repositories>
Aquí le indicamos a Maven que busque en los repositorios repo1 y java.net los diferentes
artefactos.
Conclusiones
Maven es una excelente herramienta que nos ayuda en diferentes ciclos de vida de nuestra
aplicación, de una forma muy sencilla.
Maven tiene un manejo de dependencias, que facilita mucho el estar buscando información
acerca de cuales jar ocupa un Framework o librería, encontraste, nuestra aplicación puede
inflarse mucho, por incluir jar de funcionalidades de un Framework que no ocupamos por
ejemplo, pero son incluidas.
Maven es una herramienta muy escalable y configurable, se puede integrar con los frameworks
más populares entre otras cosas.
Comentarios
Gracias por compartir ésta información.
http://m2eclipse.sonatype.org/update/
Solo agreguen esa dirección en los Soft Upds de eclipse y listo. El plugin crea nuevos proyectos Maven, permite agreguar nuevas dependencias, corre diferentes objetivos, etc
La tarea que utiliza Maven para eliminar (limpiar) los directorios en donde se ha deployado el proyecto es:
mvn clean
Ignorar mvn clear.