Construcción de ejecutables y manejo de dependencias: Maven

Un proyecto de software relativamente grande donde trabaja más de un desarrollador tenemos que existen:

  • Muchos y diversos archivos de código fuente (decenas, cientos, miles)
  • Gran cantidad de datos de configuración de las herramientas, los frameworks, y otros.
  • Muchas librerías en diferentes versiones (de terceros, propias, locales) y con dependencias entre ellas.

Construir un ejecutable es un proceso complejo que va más allá de compilar las fuentes. Poner el funcionamiento la aplicación implica realizar un despliegue cuya complejidad dependerá del servidor de aplicaciones, la base de datos, la seguridad, y muchos otros elementos que se deben tener en cuenta.

Para que los equipos de desarrollo puedan funcionar correctamente, estos procesos deben ser iguales, repetibles y automatizados. Afortunadamente, hoy día existen muchas herramientas para apoyar estas labores. Estas herramientas son dependientes del lenguaje de programación en el que está escrito la aplicación. Es común además, tener la aplicación en varios lenguajes, lo que implica que se necesitan varias herramientas para hacer estas tareas. Hay dos grandes servicios que esperamos de estas herramientas:

  • Soporte al ciclo de vida de los ejecutables de una aplicación (compilar, empaquetar, probar, desplegar, ejecutar)
  • Manejo de librerías y dependencias

La siguiente tabla muestra algunos ejemplos de estas herramientas para diferentes lenguajes:

Lenguaje Herramienta Soporte Ciclo de Vida Manejo de librerías
Java Ant Es una herramienta de automatización de tareas general. El soporte a las tareas de ciclo de vida se puede definir.
Maven OK OK
Scala Scala-Maven OK OK
Javascript bower Ayuda a manejar las dependencias de las librerías javascript
grunt OK

Maven

Queremos construir un producto de manera repetible: siguiendo el mismo proceso y utilizando las mismas fuentes, versiones de librerías, datos de config, etc. Si el proceso no está bien definido, puede pasar que:

  • Se usen las librerías o las versiones de las librerías que no son
  • No haya certeza sobre cuáles fuentes se empaquetaron
  • No estén resueltas las dependencias entre los componentes
  • No se haya probado la aplicación que se empaquetó
  • No esté bien configurado el servidor para el despliegue
  • Cada desarrollador puede eventualmente hacer un proceso distinto y crear inconsistencias.

Maven es una herramienta creada en 2001 por Jason van Zyl para algunos proyectos de Apache (ver historia de Maven) para administrar la construcción de (ejecutables de) del software.

Las principales actividades para las que Maven da soporte son:

  • Administrar las librerías y sus versiones (de terceros y propias)
  • Definir el proceso de construcción y automatizarlo
  • Manejar las dependencias entre componentes
  • Reportar y documentar el proceso y sus resultados

Adicionamente, Maven se integra con otras herramientas de tal forma que el proceso de construcción puede incluir, entre otras cosas:

  • Ejecución de pruebas a distintos niveles
  • Generación de código
  • Despliegue de la aplicación sobre distintos servidores
  • Reporte en tableros de control sobre la calidad el código

Maven es una herramienta fundamental para el proceso de Integración Continua en proyectos Java o Scala.

A continuación vamos a explicar las principales características de Maven.

Módulos y artefactos

En el contexto de maven, un módulo es un proyecto distinto y el tipo de proyecto determina el artefacto que se construirá a partir de sus fuentes. El artefacto es el resultado final de un proceso de construcción y está liso para ser desplegado en el ambiente donde se ejecutará. Un empaquetado es un zip file que, dependiendo de su tipo, empaqueta siguiendo una estructura estándar. Por ejemplo, .war para proyectos web, .jar para proyectos java, o .ear para empaquetados que contienen varios paquetes. Note que las librería en java son archivos .jar. Un archivo .jar es un artefacto en maven cuando se conoce de manera precisa:

  • Su identificado único o GAV (Group-Artifact-Version)
  • El repositorio donde se encuentra y se puede obtener

Cada módulo o proyecto maven tiene un archivo llamado pom.xml que contiene la información de su tipo, su identificación, sus dependencias y otros elementos para las actividades de construcción del artefacto. Este archivo se escribe utilizando un dialecto xml que está definido en esté enlace: maven pom.xml.

Identificación de artefactos

Un artefacto maven está identificado por su GAV:

  • Group Id: Nombre del grupo de proyectos. Relacionados con la compañía o con el nombre de la aplicación. Debe ser único (worldwide).
  • Artifact Id: Nombre del componente o aplicación (proyecto:
  • Version: Identificador de la versión del componente

<%ace edit=true, lang='java'%> <?xml version="1.0" encoding="UTF-8"?>

4.0.0

<groupId>co.edu.uniandes.csw</groupId>
<artifactId>book_201620</artifactId>
<version>1.0-SNAPSHOT</version>
...

<%endace%>

Otros atributos básicos

  • Package Name : Empaquetamiento donde inicialmente será empaquetado el componente (el resultado del build)
  • Name: Nombre del proyecto

<%ace edit=true, lang='xml'%> <?xml version="1.0" encoding="UTF-8"?>

4.0.0

<groupId>co.edu.uniandes.csw</groupId>
<artifactId>book_201620</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>book_201620</name>

... </project> <%endace%>

Estructura de los proyectos

Estructura Proyectos Maven Java

Proyectos POM y construcción de multi módulos (subsistemas)

Un producto de software puede ser definido como una combinación de varios módulos o subsistemas. En nuestro ejemplo de Book tenemos que hay un proyecto principal que tiene un pom.xml que define los dos módulos que componen el proyecto: el web y el back. El siguiente código muestra este archivo:

<%ace edit=true, lang='xml'%>

4.0.0

<groupId>co.edu.uniandes.csw</groupId>
<artifactId>book</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
    <module>book-web</module>
    <module>book-back</module>
</modules>

<%endace%>

Cuando se ejecute sobre este proyecto una acción maven, como por ejemplo Clean and Build, esta acción se ejecutará sobre cada uno de los módulos.

Herencia entre los archivos POM

Tener un archivo POM.xml padre en el proyecto principal ayuda a factorizar las dependencias, plugins y otras configuraciones y no tener que escribirlas en varios archivos.

<%ace edit=true, lang='xml'%>

4.0.0 company-logic company.logic co.edu.uniandes.csw.company company 0.1.0 ../pom.xml javax javaee-api 7.0 provided org.eclipse.persistence eclipselink 2.6.2 <%endace%>

Ciclo de Vida

Default lifecycle

  1. generate-sources/generate-resources
  2. compile
  3. test
  4. package
  5. integration-test (pre and post)
  6. Install
  7. deploy

Manejador de librerías y Dependencias

Depósitos de Dependencias

Los artefactos en Maven se guardan en depósitos de artefactos. Cada artefacto tiene su identificador único o GAV lo que permite hacer búsquedas fácilmente para localizar los artefactos y descargarlos donde se requiera. Maven maneja 3 niveles de depósitos:

  • Local: en la máquina del desarrollador (.m2)
  • Global: en el sitio de Maven
  • Empresarial: en un sitio definido por la organización que desarrolla el proyecto

El depósito local se guarda en la máquina del desarrollador. Cuando se necesita una librería, Maven busca primero allí. La imagen muestra la estructura del depósito:

Los repositorios globales son depósitos públicos que almacenan librerías de uso compartido. Por ejemplo el repositorio mismo de Maven o el repositorio público de Jboss, Glassfish o maven central.

El depósito central de Maven se puede ver aquí, tiene una búsqueda con la palabra junit: central repository

Los repositorios Empresariales tiene la misma estructura que el repositorio local con la diferencia que almacena librerías de uso compartido a nivel de red. En el pom.xml se debe definir la localización del repositorio:

<%ace edit=true, lang='xml'%>

... my-internal-site http://myserver/repo ... <%endace%>

Hay varias herramientas de repositorios empresariales. Las más populares son Nexus, Archiva, Artifactory.

Cuando se buscan las dependencias (por ejemplo durante la compilación), Maven primero busca en el repositorio local .m2, si no las encuentra recurre a sus repositorios empresariales y en caso de no encontrar ahí busca en los repositorios globales.

Definición de dependencias

Una dependencia se describe utilizando:

  • su GAV,
  • el tipo de empaquetado jar, war, pom, y
  • el alcance (cuándo o para qué acciones se requiere la dependencia). El alcance puede ser:
    • Compile: scope por defecto. Las dependencias están disponibles en el proyecto y en sus proyectos dependientes.
    • Provided: se espera que el JDK, la aplicación o el contenedor provea la dependencia
    • Runtime: la dependencia no es requerida en tiempo de compilación pero sí para la ejecución.
    • Test: son dependencias que son requeridas solo cuando se compila y ejecuta los test.
    • System: similar a provided pero se le debe indicar el jar que contiene la dependencia
    • Import: Indica que el POM utilizado debe ser remplazado con las dependencias que éste tenga en su sección

Por ejemplo, en el siguiente fragmento se esta declarando la dependencia a la versión 2.5 de la librería servlet-api.jar que tiene el groupID javax.servletv. El alcance de la librería esprovided` (default=compile)

<%ace edit=true, lang='xml'%>

... javax.servlet servlet-api 2.5 provided jar <%endace%>

results matching ""

    No results matching ""