jueves, diciembre 18, 2008

Guía de supervivencia para Maven

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





  • test

    • java

      • cr/co/jsanca/mavenexample/AppTest.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.


http://maven.apache.org/


4 comentarios:

Roy. dijo...

Excelente comentario.

Gracias por compartir ésta información.

jsanca dijo...

Con todo gusto!

jsanca dijo...

Solo agregar que pueden encontrar un plugin de Maven para Eclipse en:

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

martini dijo...

Fe de erratas:
La tarea que utiliza Maven para eliminar (limpiar) los directorios en donde se ha deployado el proyecto es:
mvn clean

Ignorar mvn clear.