Mavenización de proyectos legacy

3
7422

En este tutorial vamos a aprender una serie de nociones básicas a la hora de añadir soporte Maven a un proyecto de tipo java heredado, ayudándonos a gestionarlo y a automatizar tareas como su despliegue.

Índice de contenidos

1. Introducción

A lo largo de nuestra vida tendremos que mantener proyectos que ya se encuentren en proceso de desarrollo, pero en numerosas ocasiones estos proyectos no incluirán soporte Maven.

Maven es una herramienta a través de la cual podemos gestionar nuestro proyecto software, automatizando tareas como la compilación del mismo, el despliegue, la ejecución de sus test, la generación de documentación, etc.

Si queremos que el trabajo llevado a cabo una vez el proyecto caiga en nuestras manos sea mucho más cómodo, en caso de no estar basado en Maven, podemos mavenizarlo. Para ello, vamos a ver una serie de claves sobre la herramienta que nos ayudarán bastante.

2. Estructura de un proyecto Maven

Todo proyecto de tipo Maven tiene una estructura de directorios muy característica, la cual podemos ver a continuación:

estructura_maven

Cada una de las carpetas de la jerarquía contiene lo siguiente:

  • src: código fuente, ficheros de configuración, recursos y demás. Es decir, todo salvo el directorio de salida (target) y el pom.xml
  • main: desarrollo de la aplicación, independientemente de los test
  • test: desarrollo de los test de la aplicación
  • config: ficheros de configuración en el proyecto
  • java: clases java que contienen el código fuente de la aplicación
  • resources: recursos que se incluirán en el empaquetado y serán usados por la aplicación, como pueden ser ficheros de texto o scripts
  • webapp: contiene todos los ficheros correspondientes a la propia aplicación web que no sean código java

El primer paso de la mavenización de nuestro proyecto será crear la nueva estructura de directorios y migrar todos los ficheros a la misma.

3. El fichero pom.xml y la gestión de dependencias

Este fichero debe ir en el directorio raíz del proyecto, y contiene la descripción y la configuración del mismo. Aquí incluiremos las dependencias correspondientes a las librerías necesarias en el proyecto, los repositorios a los que pertenecen, las propiedades de entorno en base a los distintos perfiles e información sobre el tipo de empaquetado, principalmente.

También añadiremos información relativa al proyecto, como la versión en la que se encuentra o qué módulos engloba. A su vez, cada uno de estos módulos deberá contener en su directorio raíz su propio fichero pom.xml.

3.1. Etiquetas básicas

Algunas de las etiquetas básicas que contiene el fichero pom.xml son las siguientes:

  • project: Es la etiqueta que recoge todas las demás.
  • modelVersion: Indica qué versión de la especificación POM se está utilizando.
  • groupId: Identificador único del grupo de proyectos dentro de la organización en la que nos encontremos. Suele coincidir con el nombre base del paquete java, añadiendo el nombre del proyecto.
  • artifactId: Identificador único del artefacto correspondiente al proyecto. Por defecto será el nombre de paquetería.
  • version: Versión del proyecto en la cual estamos trabajando. Se le puede añadir el sufijo SNAPSHOT para indicar que es una versión en desarrollo.
  • packaging: Tipo de empaquetado del proyecto (jar, war, esb…)
  • name: Nombre del proyecto.
  • description: Descripción del proyecto.
  • dependencies: Dentro de esta etiqueta incluiremos las dependencias necesarias, cada una de ellas precedida de la etiqueta dependency. En la web http://mvnrepository.com/ podremos encontrar cualquiera de ellas, facilitándonos la plataforma el texto que debemos añadir en el pom.xml para incluirlas en el proyecto.

A continuación tenemos un ejemplo muy sencillito de pom.xml, en el cual se pueden ver todas las etiquetas enumeradas.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="
<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance
</a>"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
<a href="http://maven.apache.org/maven-v4_0_0.xsd">http://maven.apache.org/maven-v4_0_0.xsd
</a>">



       
<modelVersion>4.0.0</modelVersion>
       
<groupId>com.autentia</groupId>

       
<artifactId>autentiaNegocio</artifactId>

       
<packaging>jar</packaging>
       
<version>1.0-SNAPSHOT</version>
       
<name>Maven Quick Start Archetype</name>
       
<dependencies>
               
<dependency>

                       
<groupId>junit</groupId>
                       
<artifactId>junit</artifactId>
                       
<version>4.12</version>
                       
<scope>test</scope>
               
</dependency>
               
<dependency>
                       
<groupId>log4j</groupId>
                       
<artifactId>log4j</artifactId>

                       
<version>1.2.17</version>
               
</dependency>
       
</dependencies>

</project>

3.2. Transitividad de las dependencias

Dentro del ámbito de cada dependencia podemos indicar su transitividad mediante la etiqueta scope, dando información sobre dónde se encuentra disponible la dependencia y sobre cuándo será necesaria. Este scope podrá ser de 6 tipos distintos:

  • compile: Es el valor por defecto, el que se aplica si no especificamos ningún scope. Con este modo, las dependencias se propagarán a todos los proyectos dependientes, y estarán disponibles en todos los classpath.
  • runtime: La dependencia solo es necesaria en tiempo de ejecución, no en tiempo de compilación.
  • test: La dependencia solo es necesaria en tiempo de compilación y en la ejecución de tests.
  • provided: La dependencia será encontrada en la JDK o en un contenedor en tiempo de ejecución.
  • system: Funciona de manera similar al scope provided, pero es necesario proporcionar el JAR.
  • import: Se utiliza para importar dependencias definidas en otros pom.xml.

Es importante saber qué scope debemos asignar a cada una de las dependencias, ya que un scope erróneo puede dar lugar a errores en la aplicación, tanto en tiempo de compilación como en tiempo de ejecución.

3.3. Exclusión de librerías

También podemos excluir ciertas librerías al incluir una dependencia, con la etiqueta exclusions. Aquí tenemos un ejemplo, donde estamos excluyendo la librería jms de la dependencia oscache:

<dependency>
        <groupId>opensymphony</groupId>

        <artifactId>oscache</artifactId>

        <version>2.4</version>


        <exclusions>
                <exclusion>

                        <groupId>javax.jms</groupId>
                        <artifactId>jms</artifactId>

                </exclusion>
        </exclusions>

</dependency>

3.4. ¿Y cuáles son las dependencias que debemos añadir?

Seguramente tengamos en nuestro proyecto una carpeta llamada lib, que contiene un montón de librerías en formato jar. Basta con buscar cada una de esas librerías en la web http://mvnrepository.com/ y copiar la referencia a dicha dependencia (que aparece entre las etiquetas dependency).

Si en algún momento tenéis dudas o problemas sobre las dependencias a importar para una clase en concreto, no dejéis de visitar el tutorial de Iván Zaera sobre Obtención de información de clases Java en aplicaciones web. En él, nos propone una página JSP en la que se vuelca mediante reflexión toda la información disponible sobre cualquier clase.

Tras completar todas las dependencias en el fichero pom.xml podremos prescindir de los ficheros de librerías.

4. El proyecto parent y sus módulos

Dentro de un mismo proyecto pueden existir varios módulos, funcionando cada uno de ellos como proyectos más pequeños. Denominaremos proyecto parent al proyecto que los engloba. En su fichero pom.xml deberá aparecer la referencia a todos esos módulos a través de la etiqueta modules, de la siguiente forma:


<modules>

        
<module>modulo-uno
</module>
        
<module>modulo-dos
</module>
        
<module>modulo-tres
</module>

</modules>

Además, en el pom.xml de cada módulo deberá aparecer la referencia al proyecto padre. 



<parent>

        
<groupId>com.autentia
</groupId>

        
<artifactId>autentiaNegocio
</artifactId>

        
<version>1.0.0-SNAPSHOT
</version>

</parent>



Como podemos ver en el ejemplo, en la referencia al proyecto padre aparece la versión del mismo. No será necesario añadir de nuevo la etiqueta version, pues la versión será la misma.



Cada módulo deberá tener la estructura típica de Maven, mientras que el proyecto parent constará de un directorio que contenga su propio fichero pom.xml y una carpeta por cada módulo.

5. Los repositorios de dependencias

En caso de disponer de un repositorio remoto donde se alojen parte de las dependencias, como por ejemplo un Nexus, debemos añadirlo en la especificación del proyecto. Para ello, añadimos la referencia en el fichero pom.xml de la siguiente forma:


<repositories>

        
<repository>

                
<id>autentia-repository
</id>

                
<name>Autentia Repository
</name>

                
<url>url-del-repositorio
</url>
        
</repository>

</repositories>

Podemos añadir tantos repositorios como sean necesarios.

6. Configurando el proyecto para liberar versiones

Si queremos configurar el proyecto Maven para que al generar una release se libere una nueva versión, subiendo la etiqueta de la misma, será necesario indicar el path del repositorio remoto. Esto se hace a través de la etiqueta Maven scm, como podemos ver a continuación:


<scm>

        
<connection>
                scm:git:http://localhost/repoAutentia.git

        
</connection>



        
<developerConnection>

                scm:git:http://localhost/repoAutentia.git
        
</developerConnection>

        
<url>
                http://localhost/repoAutentia.git

        
</url>

</scm>

También debemos indicar la referencia al repositorio que almacena cada release del proyecto:


<distributionManagement>

        
<repository>
                
<id>repoAutentia
</id>
                
<name>Nombre del repositorio
</name>

                
<url>http://localhost/repositorio
</url>

        
</repository>

</distributionManagement>

7. Definiendo los plugins para compilar y empaquetar

Ya solo nos queda configurar la compilación y empaquetado del código de nuestro proyecto. Gracias a los plugin de Maven podemos hacer que nuestra configuración sea lo más completa o personalizada posible, definiendo a través de los mismos de qué manera queremos que Maven haga las cosas. Para configurar nuestro proyecto añadiremos las etiquetas build y plugins, incluyendo dentro del ámbito de las mismas todos los plugins que creamos necesarios.



Vamos a ver un ejemplo de configuración, en la que indicamos que se compile el código fuente con la versión de Java 1.7.


<build>
        
<plugins>
                
<plugin>

                        
<groupId>org.apache.maven.plugins
</groupId>

                        
<artifactId>maven-compiler-plugin
</artifactId>

                        
<version>3.5.1
</version
>

                        
<configuration>
                                
<source>1.7
</source>
                                
<target>1.7
</target>

                        
</configuration>

                
</plugin>

        
</plugins>

</build>

Maven tiene muchísimos otros plugins, disponibles a través del enlace https://maven.apache.org/plugins/index.html. Otro ejemplo de configuración es el siguiente: si queremos copiar ciertos recursos al directorio de salida del proyecto, podemos utilizar el plugin maven-resources-plugin, como se muestra a continuación:

<plugin>

        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>

        <version>3.0.1</version>

        <executions>
                <execution>

                        <id>copy-project-resources</id>
                        <phase>generate-resources</phase>

                        <goals>
                                <goal>copy-resources</goal>
                        </goals>

                        <configuration>

                        <outputDirectory>

                                ../MavenProject/target/generated-resources

                        </outputDirectory>

                                <overwrite>true</overwrite>
                                <resources>
                                        <resource>

                                                <directory>

                                                        ../MavenProject/src/main/resources/

                                                </directory>
                                                <includes>

                                                        <include>resource1.txt</include>
                                                        <include>resource2.txt</include>

                                                </includes>

                                        </resource>

                                </resources>
                        </configuration>

                </execution>
        </executions>

</plugin>

En este ejemplo estamos copiando los recursos resource1.txt y resource2.txt del directorio ../MavenProject/src/main/resources/ al directorio ../MavenProject/target/generated-resources.

Por supuesto, en último lugar queda resolver todos los errores de compilación que nos reporte nuestro entorno de desarrollo, al igual que los errores sucedidos en tiempo de ejecución en nuestro servidor.

8. Conclusiones

Mavenizar un proyecto no es algo trivial. Tras haber seguido todos los pasos recogidos en este tutorial nos habremos dado cuenta de que cada proyecto tiene sus propias características y requiere una serie de acciones, pero tras acabar el proceso su estructura será muy similar a la de cualquier otro proyecto basado en Maven.

A partir de ahora, ahorraremos mucho tiempo en la gestión de nuestro proyecto gracias a esta herramienta. Y lo mejor de todo, trabajar en él será muchísimo más cómodo, pues podremos realizar de forma automática tareas que hasta ahora hacíamos manualmente.

3 COMENTARIOS

  1. En mi opinión el tutorial intenta abordar aspectos triviales de la herramienta sin explicar como funciona, esto es, ciclo de vida , convención sobre configuración, plugins etc. Además habla de herramientas como Nexus sin entrar en detalle y otra cuestiones como agregación de proyectos. Creo que se queda a medio camino de su objetivo, porque para un usuario con conocimientos de maven no le aporta nada y para alguien que empiece es demasiado superficial. Dicho esto enhorabuena por el esfuerzo y gracias por compartir.

    • Te agradezco el comentario, Juan, y sobre todo que te hayas tomado unos minutos para leer este artículo 🙂

      Lo que pretendía con este tutorial no era explicar los conceptos básicos de Maven, sino señalar algunos aspectos clave que se deben tener en cuenta al «mavenizar» un proyecto. Si hemos trabajado con proyectos Maven ya configurados es muy probable que tengamos ciertos conocimientos sobre la herramienta, y que incluso sepamos qué significa cada uno de los elementos de configuración del fichero pom.xml. Pero, si nos enfrentamos a esta tecnología en un proyecto donde Maven no esté presente, es posible que demos por hecho algunos detalles y que nos olvidemos de ellos al dar soporte Maven a la aplicación que vayamos a adaptar.

      En cuanto al nivel de detalle, he intentado explicar todo de la forma más genérica posible pero destacando los elementos de configuración que considero más importantes. Cada proyecto es un mundo, pero con las claves que os doy seguramente os sea más fácil indagar en los detalles más específicos de la configuración de vuestra aplicación.

      ¡Saludos!

    • Buen trabajo,en verdad he trabajado con proyectos maven, y me preguntaba como voy mavenizar un proyecto que no usa maven, ya sabré que hacer ya que el procedimiento lo estás dando,sólo pediría algo de modestia con la gente que cree saber mucho, no es lo mismo convertir un proyecto grande a maven que un proyecto de curso de Academia,ya que ahí sólo hacemos un click derecho y ya está. Gracias por el aporte.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad