Creacion de Arquetipos Personalizados
Contenido
Estructura de un arquetipo
El arquetipo se implementa a través de un proyecto Maven y tiene una estructura básica bastante sencilla.
arquetipo-personalizado |-- pom.xml `-- src `-- main `-- resources |-- META-INF | `—maven | |-- archetype.xml (deprecado) | `-- archetype-metadata.xml `-- archetype-resources |-- pom.xml `-- __rootArtifactId__-LibModule |-- pom.xml `-- src |-- main `-- java `-- test `-- java
En el archivo pom.xml en el raiz del proyecto se configuran solamente los datos básicos, como el nombre del arquetipo y el paquete al que pertenece. Luego utilizaremos estos datos durante el proceso de creación de un proyecto nuevo.
En la carpeta maven se ubica el archivo de estructura del proyecto archetype-metadata.xml en el cual se configuran los archivos que se van a copiar durante el proceso de creación del proyecto. Ademas se pueden los submódulos que contiene el proyecto, en caso que el proyecto sea multimódulo.
La carpeta archetype-resources contiene todos los archivos y la estructura de carpetas a utilizar durante el proceso de creación.
archetype-metadata.xml
Dentro del archivo archetype-metadata.xml se define el conjunto de archivos a copiarse, en un estilo muy similar al del Ant. El arquetipo multimódulo es el más complejo y completo de todos, por lo que se elaboró uno a nivel de ejemplo. El siguiente arquetipo define un módulo padre, que a su vez contiene un submódulo, de tipo librería (cuyo generado es un archivo Jar)
<?xml version="1.0" encoding="UTF-8"?> <archetype-descriptor name="multi-module"> <fileSets> <fileSet filtered="true" packaged="false"> <directory></directory> <includes> <include>pom.xml</include> </includes> </fileSet> </fileSets> <modules> <module id="${rootArtifactId}-LibModule" dir="__rootArtifactId__-LibModule"> <fileSets> <fileSet filtered="true" packaged="true"> <directory>src/main/java</directory> <includes> <include>**/*</include> </includes> </fileSet> <fileSet filtered="true" packaged="true"> <directory>src/test/java</directory> <includes> <include>**/*</include> </includes> </fileSet> <fileSet filtered="true" packaged="true"> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </fileSet> <fileSet filtered="true" packaged="true"> <directory>src/test/resources</directory> <includes> <include>**/*</include> </includes> </fileSet> <fileSet filtered="true" packaged="false"> <directory></directory> <includes> <include>pom.xml</include> </includes> </fileSet> </fileSets> </module> </modules> </archetype-descriptor>
El primer detalle a tener en cuenta es el nombre del descriptor del arquetipo. Para que soporte múltiples submódulos es necesario setearlo en multi-module.
La propiedad filtered en el tag fileset permite que se utilicen las variables y que se reemplacen de forma dinamica.
La propiedad packaged hace que en cada uno de los directorios definidos, se empaquete utilizando la propiedad groupId.
En caso que no se defina directorio, se toma el raiz como referencia.
En el nombre del submódulo se utiliza la variable ${rootArtifactId}, que sirve para referenciar el nombre del módulo padre. El formato ${xxxxxx} se utiliza para referenciar una variable dentro de cualquier archivo; para los directorios y nombres de archivos se utiliza el formato __xxxxxx__ como se puede apreciar en la propiedad dir.
archetype-resources
En el directorio archetype-resources se encuentran todos los recursos que se van a copiar durante la creación de un proyecto.
Durante el proceso de copia, se reemplazarán las variables utilizadas en los nombres del recursos, así como dentro de los recursos.
Puede contener submódulos, siendo estos previamente configurados en el archivo archetype-metadata.xml.
Las variables
Existen algunas variables básicas que se pueden utilizar durante la creación del arquetipo.
- groupId: Paquete a utilizar en el proyecto nuevo
- artifactId: Nombre del proyecto
- version: Versión del proyecto
En caso que el arquetipo contenga submódulos, también se pueden utilizar estas variables:
- rootArtifactId: Es el identificador del proyecto raiz.
- parentArtifact: Dentro de un subproyecto, es el identificador del proyecto padre.
Además en la metadata del arquetipo se pueden definir variables propias, con ciertos valores predeterminados, los cuales se puede sobreescribir en el momento de creación de un proyecto.
<requiredProperties> <requiredProperty key="propiedad-con-valor-default"> <defaultValue>valor-default</defaultValue> </requiredProperty> <requiredProperty key="propiedad-sin-valor-default"/> </requiredProperties>
Escaping
Apache Velocity (que es el framework de templating utilizado por Maven) utiliza el signo "$" como identificador. Dado que se utilizan variables dentro de algunos archivos, como los pom, el generador de arquetipo puede confundirse sobre cuales variables reemplazar y cuales dejar intactas. Es por ello que es necesario distinguir un caso del otro de forma explicita, utilizando una variable de escape para aquellas variables que se desean copiar texturalmente.
Ejemplo:
#set( $symbol_dollar = '$' ) <project> <name>${symbol_dollar}{project.artifactId}</name> </project>
Instalación del arquetipo
Para poder usar el arquetipo va a ser necesario primero instalarlo en el repositorio de código. Para ello hay que ejecutar:
mvn clean install
Nota: el comando clean no es necesario, pero puede evitarnos dolores de cabeza en caso que haya algún problema, al garantizar que se elimina la versión anterior del arquetipo.
Creación de proyecto usando el arquetipo
Para generar un proyecto nuevo utilizaremos la tarea archetype:generate a la cual se pasaremos los siguientes parámetros:
- archetypeGroupId: Nombre del paquete de arquetipos que vamos a utilizar
- archetypeArtifactId: Nombre del arquetipo
- archetypeVersion: Versión del arquitipo
- groupId: Paquete a utilizar en el proyecto nuevo
- artifactId: Nombre del proyecto
- version: Versión del proyecto
La tarea archetype:generate en caso que no se le pasen parámetros solicitará los mismos de forma interactiva y antes de terminar el proceso solicitará una confirmación. En caso que se desee anular este comportamiento, se le puede pasar el parámetro extra:
- interactiveMode=false
Ejemplo:
mvn archetype:generate -DarchetypeGroupId=com.dosideas -DarchetypeArtifactId=dosideas-archetype-javaee -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=com.dosideas.maven -DartifactId=helloworld -Dversion=1.0 -DinteractiveMode=false
Nota: la tarea archetype:generate reemplaza a la anterior tarea archetype:create la cual no debe ser utilizada porque carece de las opciones más avanzadas que se utilizan en los últimos plugins.