Mostrando las entradas con la etiqueta maven. Mostrar todas las entradas
Mostrando las entradas con la etiqueta maven. Mostrar todas las entradas

Notificaciones automáticas de cambios incluidos en un release usando Maven

Hola todos!
Hace tiempo que no escribía, así que acá va una nueva entrada. Antes que nada, los que habrán leído alguna nota el año pasado o antes, habrán notado que la dirección del sitio cambió, la idea es apuntar un poco más a novedades y noticias en el mundo de los frameworks de las plataformas que manejo, con algún comentario de las cosas que me parecen interesantes, veremos si puedo llevarlo adelante.
Hoy quiero contarles acerca la experiencia que tuve, al querer implementar algo que, a priori, hubiera parecido bastante simple de hacer en el mundo de Maven, pero que, sorpresivamente no lo fue. De hecho fue la primera vez desde que utilizo esta herramienta, que tuve que tocar algo de código de un plugin desarrollado, ya que ninguna de las opciones que encontré pudo funcionar.
Lo que necesitaba (o mejor dicho, quería implementar) era poder enviar notificaciones automáticas vía correo electrónico, a los desarrolladores, cuando alguien hacía un release de uno de los componentes que utilizamos internamente en el lugar en donde trabajo.
Lo primero que hice, fue investigar dos plugins que realizaban parte de la tarea:
  • Maven Changes Plugin: Este plugin construye una página o notificación, enumerando los "cambios" que tuvo un artefacto dado. Además ofrece la posibilidad de enviar el anuncio vía correo electrónico. Ya se lo que pensarán, este es el indicado, pero no. El problema es que elabora todo en base a dos orígenes: un archivo .xml que lista los cambios (changes.xml), o sino utiliza un repositorio de issues como Jira o Trac. Justamente en mi trabajo no usamos ninguno de esos repositorios de issues por lo que ninguno de los orígenes de "cambios" me servía. Yo necesitaba que tome los mismos del SVN (repositorio de código).
  • Maven Changelog Plugin: Este otro tenía justamente lo que el anterior no tenía, es decir, lo que hace es elaborar un reporte que lista los cambios que existen en el repositorio de código. El problema es que es lo único que hace (o sea, no arma anuncios ni envía correos). Además el reporte es bastante pobre, ya que no "decora" de ninguna manera los commits, no enlaza los issues a nuestra herramienta de gestión de issues, ni nada por el estilo.
Bastante decepcionado seguí buscando a ver si encontraba algo que podría servirme sin éxito. Hasta que ingresé al repositorio de plugins de Codehaus. Buscando en este lugar, encontré un plugin bastante interesante, el SCM Changelog Maven plugin. Inicialmente parecía ser la solución, ya que creaba un reporte bastante parecido al que genera el Maven Changes Plugin, pero lamentablemente no enviaba anuncios. Igualmente lo investigué para por lo menos poder crear el reporte, pero me encontré con otros problemas:
  • Cuando quise ejecutarlo, me encontré con que arrojaba una excepción, buscando en la lista de issues abiertos, lamentablemente encontré que el problema no estaba solucionado aún.
  • No encontré ninguna configuración que permita filtrar los textos de los commits, esto era importante debido a que como utilizamos releases automáticos vía maven, muchos textos sería interesante que no aparezcan, ya que se trata de commits automáticos.
  • Si bien soporta el concepto de Grammars, para identificar los issues que uno menciona en los textos de los commits, necesitaba la posibilidad de definir una grammar personalizada, ya que utilizamos una forma especial de nombrar los issues. Esto sumado al hecho de que los issues los tenemos almacenados en una herramienta propietaria (ni Jira ni Trac+)
Debido a todos estos problemas, decidí ponerme manos a la obra, descargarme el código fuente del plugin y ver si podía solucionarlos.
Luego de investigar y probar, logré solucionar el primer problema, el cual ocurría debido a que en Maven 3, se cambió todo el mecanismo de generación de reportes y manejo de repositorios, haciendo que no se pueda subclasear el repository manager para agregarle nuevas características.
Lo que hice fue modificar la clase ScmActivityReport, e instanciar el repository manager usando el BasicScmManager, ya que no era necesario reemplazar el que provee Maven, ya que el único uso es generar el reporte, y con ese era suficiente.

Instanciación del BasicScmManager
Instanciación del BasicScmManager
En esa clase también aproveché para hacer algunas modificaciones visuales al reporte, como por ejemplo ponerle un border a la tabla, comentar la sección de resumen, hacer que las referencias a los íconos sean a imágenes públicas y poner un título personalizado. 
El segundo paso fue crear un nuevo Grammar, el cual como primer medida, filtra de todos los mensajes de los commits, todos los que tengan el texto "maven-release-plugin", esto es porque no quiero que aparezcan como cambios los commits que haga el plugin de maven, ya que no aportan nada al changelog.
Además aproveché el hecho de tener un nuevo grammar propio, y modifiqué los patrones de búsqueda de issues en el texto del comentario del commit, para que encuentre los issues que yo quería que encuentre.
Para crearse su propio grammar, pueden ver la documentación del plugin, que es bastante simple.
Otra cosa que tuve que hacer, fue tocar la clase SvnScmAdapter y comentar ciertas líneas (104-115) que agregaban como un "release" a los cambios hechos en el trunk. Eso era algo que no necesitaba, ya que lo que yo quería, era apuntar a los tags que crea el Maven Release Plugin.
Finalmente tuve que implementar unos cambios en la clase SvnListConsumer, ya que el filtrado de tags aceptados se hacía antes de agregar un tag ficticio que contiene los cambios hasta antes de la creación del primer tag, lo cual es un problema, ya que lo que yo necesitaba era que se muestren solamente los cambios del tag sobre el cual se hizo el release.

Modificaciones al SvnListConsumer
Modificaciones al SvnListConsumer
De todas maneras solo tenía la primer parte del trabajo realizada hasta este punto. Hasta ahora solo tenía un reporte en html, con el formato de maven, con todos los cambios de la versión que fue liberada en el build actual. Yo lo que quería era que ese reporte se envíe mediante correo electrónico.
Para esto último, estuve investigando, y de todas las opciones disponibles, la que más me gustó fue el Maven Postman Plugin, el cual, lo que hace es enviar un correo electrónico, cuyo contenido es un html presente en el directorio de construcción de nuestro proyecto.
La configuración es simple, y pueden visitar este post, en donde se explican algunos detalles importantes.
El problema, ahora, era que el reporte era generado con el look & feel de los sites de maven, con un menu al costado, etc. Yo quería que el mail enviado sea lo más "limpio" posible.
La solución fue proporcionar un nuevo template, el cual era basado en el template original, y lo que hice, fue eliminar las secciones del header, footer, y menu. Lo que sí, tuve que usar el Maven Dependency Plugin, para empaquetar el template en un artefacto aparte, y que se pueda desempaquetar en todos los proyectos de forma dinámica, y evitar tener que incluirlo dentro de cada proyecto desde el cual yo quiera enviar notificaciones.
Finalmente lo que hice fue modificar el profile "release-profile", el cual es un profile built-in el cual se activa automáticamente al momento de hacer un release. Lo que hice fue agregar las configuraciones de todos los plugins mencionados hasta ahora. Obviamente tuve que compilar mi propia version del ScmChangelogPlugin y deployarla en nuestros servidores privados de binarios. Les paso la configuración final:

 <profile>  
      <id>release-profile</id>  
      <activation>  
           <property>  
                <name>performRelease</name>  
                <value>true</value>  
           </property>  
      </activation>  
      <build>  
           <plugins>  
                <plugin>  
                     <groupId>org.apache.maven.plugins</groupId>  
                     <artifactId>maven-dependency-plugin</artifactId>  
                     <version>2.8</version>  
                     <executions>  
                          <execution>  
                               <id>site</id>  
                               <phase>package</phase>  
                               <goals>  
                                    <goal>unpack</goal>  
                               </goals>  
                               <configuration>  
                                    <artifactItems>  
                                         <artifactItem>  
                                              <groupId>assemblies-comunes</groupId>  
                                              <artifactId>assemblies-comunes</artifactId>  
                                              <version>1.0.0-SNAPSHOT</version>  
                                              <type>jar</type>  
                                              <overWrite>true</overWrite>  
                                              <outputDirectory>${project.build.directory}/unpackedAssemblies</outputDirectory>  
                                              <destFileName>optional-new-name.jar</destFileName>  
                                              <includes>**/*.vm</includes>  
                                         </artifactItem>  
                                    </artifactItems>  
                                    <includes>**/*.vm</includes>  
                                    <outputDirectory>${project.build.directory}/assemblies</outputDirectory>  
                                    <overWriteReleases>false</overWriteReleases>  
                                    <overWriteSnapshots>true</overWriteSnapshots>  
                               </configuration>  
                          </execution>  
                     </executions>  
                </plugin>  
                <plugin>  
                     <groupId>ch.fortysix</groupId>  
                     <artifactId>maven-postman-plugin</artifactId>  
                     <executions>  
                          <execution>  
                               <id>send a mail</id>  
                               <phase>site</phase>  
                               <goals>  
                                    <goal>send-mail</goal>  
                               </goals>  
                               <inherited>true</inherited>  
                               <configuration>  
                                    <from>ciserver@miempresa.com</from>  
                                    <subject>Release exitoso: ${project.artifactId}-${project.version}</subject>  
                                    <failonerror>false</failonerror>  
                                    <mailhost>mail-pruebas.miempresa.com</mailhost>  
                                    <mailuser>user</mailuser>  
                                    <mailpassword>password</mailpassword>  
                                    <htmlMessageFile>target/site/changelog.html</htmlMessageFile>  
                                    <receivers>  
                                         <receiver>Programadores</receiver>  
                                         <receiver>programadores@miempresa.com</receiver>  
                                    </receivers>  
                               </configuration>  
                          </execution>  
                     </executions>  
                </plugin>  
                <plugin>  
                     <groupId>org.apache.maven.plugins</groupId>  
                     <artifactId>maven-site-plugin</artifactId>  
                     <configuration>  
                          <templateDirectory>${basedir}/target/unpackedAssemblies</templateDirectory>  
                          <template>template-changelog.vm</template>  
                     </configuration>  
                </plugin>  
           </plugins>  
      </build>  
      <reporting>  
           <plugins>  
                <plugin>  
                     <groupId>org.codehaus.mojo</groupId>  
                     <artifactId>scmchangelog-maven-plugin</artifactId>  
                     <version>1.4-SNAPSHOT</version>  
                     <configuration>  
                          <trackerUrlPattern>http://miherramientadeissues.miempresa.com?idIssue={0}</trackerUrlPattern>  
                          <trackerType>sourceforge</trackerType>  
                          <grammar>MIGrammar</grammar>  
                          <filter>${project.artifactId}-${project.version}</filter>  
                     </configuration>  
                </plugin>  
           </plugins>  
      </reporting>  
 </profile>  

Fue complejo, pero al final logré lo que quería. Veré si tengo algo de tiempo, en contactarme con los creadores del plugin a ver si se pueden incorporar algunas de las correcciones y mejoras que implementé.
Nos vemos en el proximo post!

Maven: Como cambiar la versión de mi proyecto

Una de las quejas que suelo escuchar con respecto a Maven, es acerca de lo complicado que puede ser mantener las versiones de nuestros proyectos y componentes, actualizadas. Es verdad, si uno intenta hacerlo manualmente (es decir tocando "a pata" los pom.xml), es bastante engorroso y error-prone.
Hasta hace un tiempo existía una manera de, por ejemplo, incrementar la versión de todos los componentes, usando el plugin Release de Maven, pero ese plugin les da miedo a todo el mundo (es uno de los plugins más potentes y complejos).
Otra manera que he visto que se ha usado bastante, de mantener las versiones, es usar variables definidas dentro de los pom.xml padre, las cuales se replican en todos los pom.xml hijos. Si bien esta manera parece a primera vista, cómoda y elegante, si la ubicamos dentro de un contexto de releases frecuentes, involucrando a servidores de integración y sobre todo, al plugin de Release, termina siendo un problema, ya que no conozco manera de que dicho plugin "entienda" esas variables.
Digamos, pasando en limpio: es una forma más simple de seguir toqueteando los pom.xml de forma manual. Pero sigue siendo lo mismo.
Otro problema que tiene el enfoque anterior es que si estamos visualizando un pom.xml hijo, no sabemos cual es la versión actual, no nos queda otra que "subir" al pom padre y verlo ahí. De esto se deriva, de que si conseguimos ese pom.xml de algún artefacto, tampoco a primera mano, no tenemos forma de saber que versión es.
Corolario: La versión siempre debería estar presente en los pom.xml, el uso de variables para esto no es una buena idea.
Esto nos lleva al principio, como podemos hacer para trabajar con las versiones de los pom.xml, sobre todo cuando los proyectos son cada vez más y más grandes?
Y esto es solo la punta del iceberg, no hablamos acerca de, por ejemplo, como trabajar con las versiones de las dependencias de nuestros proyectos.
Ejemplo: pasaron 2 años de que nuestro proyecto está funcionando, y queremos mantener actualizadas las versiones de las dependencias, como hacemos? investigamos una por una cual es la última versión y vamos incrementando las mismas en cada sección dependencies de cada pom? ... y que pasa si nuestro proyecto tiene 50 modulos diferentes? como hacemos para incrementar las versiones de todos de forma simple?
Lo mismo para los plugins de maven que estamos usando ... en fin, debería existir algo para lidiar con estos temas, no?

Maven Versions Plugin

Por suerte hoy en día existe un buen plugin para trabajar con las versiones de nuestros proyectos. Este plugin tiene muchos goals, en los cuales destaco los siguientes:

  • versions:display-dependency-updates: Muestra por pantalla las nuevas versiones que existen en los repositorios que usamos, de cada una de las dependencias de nuestros proyectos.
  • versions:display-plugin-updates: Idem anterior, pero de los plugins de maven que utilizamos.
  • versions:update-parent: Actualiza la versión de nuestro "pom padre" para que apunte a la última versión disponible. Esto es muy útil si contamos con un "super pom" en nuestra organización con definiciones comunes a todos los proyectos.
  • versions:set: Este es el goal más interesante y más útil: lo que hace es justamente cambiar la versión de nuestro proyecto a nivel global. Es decir, si los componentes de nuestro proyecto tienen dependencias entre sí, las mismas también se actualizan.
  • versions:use-releasesversions:use-next-releases y versions:use-latest-releases: sirven para reemplazar las versiones snapshots por releases, incrementar al próximo release o directamente reemplazar las versiones por el último release disponible
  • versions:use-next-snapshots y versions:use-latest-snapshots: Lo mismo que lo anterior pero con SNAPSHOTS
  • versions:commit y versions:revert: Permiten implementar todos estos cambios de forma pseudo-transaccional, es decir, si no estamos conformes con los cambios (o el proyecto no compila, o no corre) podemos volver a las versiones originales de los pom.xml
En fin, existen otros goals más, pero con estos ya se puede trabajar bastante bien con versiones de proyectos grandes de forma segura y rápida.
Se animan a usarlo?

Construyendo proyectos .NET usando Maven

Los que me conocen saben que por lo general tiendo a usar Maven para todo, pero si lo hago, es porque estoy convencido de que está bueno tener un marco para ciertas tareas repetitivas, y despues de haber visto tantos enfoques, creo que lo que propone maven es bastante razonable, para prácticamente cualquier lenguaje.
Pero la idea de este post, no es hablar de lo que ofrece Maven, sino de describir cuales son las alternativas que existen hoy en día para poder utilizarlo en proyectos de la plataforma de Microsoft.
Cabe aclarar de que en mi carrera como desarrollador, comencé utilizando la plataforma .NET, antes que JAVA, cuando todavía estaba apareciendo, allá por el año 2000 (12 años ya pasaron, dios!). Luego la vida me llevó al mundo de la tacita de café, en el cual descubrí otras formas de construir aplicaciones; y luego de unos años me volví a enfrentar nuevamente a la tarea de arquitecturar y de trabajar con aplicativos de este sabor.
Acostumbrado como estaba a sistemas alineados con los lineamientos propuestos por Maven, debo confesar que pasé por varios estados de ánimo al ver que me faltaban ciertas características que ya las consideraba como básicas en todo proyecto de desarrollo, como ser el layout común de estructura de directorios, manejo de dependencias, de versionado, de releases, etc.
Entonces comencé a buscar diferentes maneras "hacer andar maven" con .NET. Ahorrando los detalles de la búsqueda, llegué a dos alternativas diferentes: NPANDAY y maven-dotnet-plugin.

NPANDAY

El primero es un proyecto al cual seguí por algunos años, comenzó como un tímido port de los plugins core de Maven pero evolucionó mucho a lo largo del tiempo, y actualmente se encuentra como proyecto incubadora en el cúmulo de Apache, lo cual no es poco.
El enfoque de este proyecto es acercar maven a los desarrolladores .NET, facilitando la vida a los que están acostumbrados a trabajar la mayor parte del tiempo, con la IDE N°1 de la plataforma: Visual Studio.
Tal es así que el proyecto está dividido en dos grandes partes: por un lado el gran conjunto de plugins que permiten hacer las tareas rutinarias (compilar, empaquetar, construir, liberar, etc.) del proyecto utilizando Maven y por otro lado un plugin para Visual Studio que permite realizar ciertas tareas (ciertas modificaciones a los archivos pom.xml, agregar dependencias, construir, etc.) desde adentro de la IDE.
Al comenzar a investigarlo, una de las cosas que no me gustó demasiado, es que el proyecto en sí, se aleja mucho de la filosofía Maven, en el sentido de que para comenzar tenemos que seguir una Guía de Instalación. Nada más alejado del espíritu Maven, de ser un software que se autoinstala en cierta manera, ya que todas  las partes que lo componen se van descargando a medida que se va utilizando. En las primeras etapas del proyecto, incluso, uno tenía que descargarse todo el repositorio completo para poder utilizarlo, y nuevas versiones de NPANDAY obligaban a tener nuevas versiones del repositorio! ... muy Microsoft :)  ... por suerte hoy en día todo está subido al repositorio mundial.
Otro de los problemas a los cuales me enfrenté, fue al hecho de que el plugin para Visual Studio, solo funciona si lo tenemos funcionando en idioma Ingles (a tenerlo en cuenta, ya que lamentablemente este tema todavía no está solucionado).
Con respecto a la documentación, que si bien existe y es bastante, me da la sensación de estar bastante desorganizada, uno no sabe por donde comenzar, sobre todo si ya tenemos un proyecto funcionando y lo queremos hacer andar con Maven, no hay una guía simple de como hacerlo. Tampoco si queremos empezar desde cero, sobre todo lo que es relacionado al manejo de dependencias. Una buena página para los que quieran comenzar, es la que muestra el listado de plugins existentes.
La verdad que luego de intentar utilizarlo llegué a varios problemas (como por ejemplo la falta de plugins de reporting, y un no muy buen esquema de directorios para el testing unitario) por lo que lamentablemente tuve que seguir buscando a ver si no existía alguna alternativa.

Maven-dotnet-plugin

Por suerte existe, este proyecto apareció tímidamente en la n-ésima búsqueda en google, y terminó sirviendo totalmente para lo que estaba necesitando. El enfoque es totalmente diferente: está pensado para las personas que ya conocen Maven, y que lo necesitan para poder construir proyectos en .NET
En este caso olvídense de plugins de visual studio y de grandes características. Es un simple proyecto que lo que intenta resolver es justamente, poder construir proyectos .NET usando Maven.
Ya desde el sitio oficial uno ya se siente a gusto con el layout utilizado, obviamente generado automáticamente por los plugins de Maven. Este proyecto si bien tiene algunas limitaciones (ej. no pude hacer andar el manejo de dependencias, lo cual lamentablemente es bastante malo), pose algunas características muy interesantes, como por ejemplo muchos plugins de reporting que funcionan de lo más bien con servidores de construcción como Jenkins (lo más interesante es que tenemos el reporte de DRY gracias al plugin CPD), una idea inicial de empaquetado de aplicaciones WEB, un muy buen enfoque de estructura de directorio e integración con Galio para el unit testing, todo esto a la Maven-way, es decir, se descarga cuando se usa.

Conclusión

Se que probablemente lo que esperaban es un análisis más detallado de las características de cada uno, pero les puedo dejar como conclusión, despues de haber utilizado las dos herramientas lo siguiente: NPANDAY se ve como un proyecto más grande, con más plugins, más líneas de código y más esfuerzo de fondo. Lamentablemente todavía tiene muchos problemas que lo hacen prácticamente inusable, y para colmo de males, el proyecto parece haberse detenido en la versión 1.4.0-SNAPSHOT, una pena realmente, ojalá en algún momento lo retomen y lo continúen. Con respecto a maven-dotnet-plugin, lo recomiendo, si bien es mucho más humilde y más simple, funciona, hace lo que promete y bien, y nos abre las puertas a tener proyectos similares, ordenados, liberables y construíbles contínuamente.
Nos vemos en el próximo post.

STAND for Android: Un buen comienzo

Investigando un poco acerca de si existía algún buen archetype para desarrollar una aplicación en Android, llegué a este proyecto que me pareció interesante. STAND for Android, sirve principalmente para comenzar un buen desarrollo, con todas las herramientas para hacerlo sólido.
Utiliza Maven, para controlar el ciclo de vida del proyecto, versiones, dependencias, etc.
Permite crear proyectos con configuraciones predefinidas de forma óptima, como ser logging, testing, etc.
Opcionalmente, las aplicaciones generadas pueden crearse ya listas, para ser publicadas en el android market.
Para comenzar a utilizarlo, es muy simple para los que están acostumbrados a utilizar el plugin de archetypes de maven, simplemente hay que correr alguno de los comandos indicados en el sitio de stand.
Luego de ejecutar algunos de los archetypes, se generará un proyecto multimódulo, con un apartado especial para los tests de integración.
Obviamente ya viene preconfigurado para usar el plugin de maven para android, y tambien todas las configuraciones necesarias para poder sacarle el provecho a las extensiones de eclipse para trabajar con Android.
Es interesante el apartado de tests de integración, ya que uno de los módulos generados está listo para correr este tipo de tests sobre la nueva aplicación.
Todo lo que vimos hasta ahora es la parte de creación de un proyecto en blanco para poder empezar a trabajar, pero eso no es todo. Ademas existen otros cuatro frameworks interesantes:
  • Rindirect: Es un plugin de maven, que permite facilitar la reutilización de codigo, a traves de varios proyectos diferentes, solucionando los problemas conocidos de dependencias y colisión de paquetes.
  • Androlog: Es una pequeña libreria para tener logging dentro de nuestras aplicaciones Android
  • Marvin: Es una libreria de testing unitario, que permite facilitar la creación de tests complejos, sobre todo relacionados a la ejecución de actividades, etc.
  • Roboject: Es un framework de inyección de dependencias mediante anotaciones para Android.
En fin, un conjunto interesante de herramientas para no tener que reinventar la rueda.

Maven: Dependencia entre wars

Por lo general, en todo proyecto empresarial JAVA, surge al momento de definir la arquitectura del aplicativo, definir el concepto de modulo, subsistema, y por que no, sistema. Al momento de tomar estas definiciones con un aplicativo en particular, surgen muchas maneras de realizar esta división, pero si tenemos en mente el stack de tecnologías JAVA estándares, para la Web, en algún momento, sobre todo dependiendo del tamaño del proyecto, vamos a llegar a la pregunta del millón: conviene separar mi capa de presentación por módulos?
Desde el comienzo, incluido en todo lo que nos ofreció el stack de tecnologías para aplicaciones empresariales de JAVA, nunca hubo un buen soporte para realizar esto, que a simple vista resulta prácticamente básico, poder “partir” mi aplicación en módulos independientes, pero en cierta manera “unidos” entre si, mediante el concepto de aplicación empresarial. Si bien se podían embeber varios paquetes “war” dentro de un único bundle “ear”, eran aplicaciones prácticamente independientes, y, era muy difícil por ejemplo, reutilizar código, ya que un WAR no es una librería (JAR) como tal.
Con la aparición de Maven, el WAR comenzó a ser un módulo más, por lo que surgió naturalmente el concepto de tratarlo como un paquete de código en si. De todas maneras los primeros intentos por lograr la tan ansiada dependencia, no vinieron de los plugins “core” sino de terceros, por ejemplo el goal maven:uberwar de cargo, o el plugin warpath de AppFuse.
Estos plugins si bien lograban su cometido, no eran la forma más natural de poder establecer dependencias entre los módulos WAR y así lograr por ejemplo, la reutilización de código de capa de presentación.
Igualmente ustedes dirán, “pero si queremos reutilizar, porque no metemos el código en librerías JAR?”, el problema viene justamente por lo que decía al principio, hasta hace no tanto, el estándar JEE, no permitía que, por ejemplo, las páginas JSPs u otros recursos WEB vengan embebidas en librerías. Si podríamos reutilizar ese código y tener en un componente principal recursos comunes, y en otros componentes simplemente referenciarlos, se disminuiría un montón el código de varias aplicaciones similares o módulos de una aplicación grande.
Otro problema venía por el lado de las IDEs, si bien podíamos resolverlo quizá, con los plugins que mencioné anteriormente, la IDE por lo general no se “daba cuenta” de esta dependencia, y había que lograr que funcione usando trucos extraños.

La solución

Por suerte se logró solucionar este problema con la última versión del plugin que administra la construcción de archivos war de maven, el maven-war-plugin.
Ahora para poder reutilizar código, podemos usar tranquilamente la dependencia entre wars, que funciona de la siguiente manera.
Supongamos que tenemos un proyecto WAR, denominado “proyecto-comun”, el cual posee clases y recursos comunes a ser reutilizados en otros modulos WAR.Además tenemos un proyecto WAR, denominado “proyecto-nuevo”, el cual necesita reutilizar clases bases y recursos existentes en el proyecto anterior. Para lograr la dependencia, tenemos que agregar las siguientes configuraciones: En el “proyecto-comun”, debemos agregar lo siguiente en el pom.xml:

 <plugin>  
      <groupId>org.apache.maven.plugins</groupId>  
      <artifactId>maven-war-plugin</artifactId>  
      <configuration>  
           <attachClasses>true</attachClasses>  
           <webModule>  
                <groupId>com.miempresa</groupId>  
                <artifactId>proyecto-comun</artifactId>  
                <contextRoot>/proyecto-comun</contextRoot>  
           </webModule>  
      </configuration>  
 </plugin>  

Acá lo importante es el tag “attachClasses”, que le dice a maven que cree un artefacto secundario con las clases del proyecto, las que más adelante nos van a servir para poder compilar el mismo.
Luego en el “proyecto-nuevo”, tenemos que agregar lo siguiente:

 <dependency>  
      <groupId>com.miempresa</groupId>  
      <artifactId>proyecto-comun</artifactId>  
      <version>1.0.0-SNAPSHOT</version>  
      <type>jar</type>  
      <classifier>classes</classifier>  
 </dependency>  
 <dependency>  
      <groupId>com.miempresa</groupId>  
      <artifactId>proyecto-comun</artifactId>  
      <version>1.0.0-SNAPSHOT</version>  
      <type>war</type>  
 </dependency>  

La primer dependencia, indica que las clases se deben compilar teniendo en cuenta el JAR generado automáticamente por el primer proyecto, y la segunda, que luego de compilar, primero copie los recursos del war anterior y luego sobre ese, los recursos del war actual, reutilizando archivos jsps, css, imagenes, xmls, etc.
Lo bueno de esta técnica, es que funciona correctamente con Eclipse (por las dudas usar siempre la última versión), utilizando el plugin m2eclipse, que por el momento es lo mejorcito que existe para trabajar con proyectos maven. La IDE correctamente interpreta la dependencia, y si tenemos los dos proyectos importados, ni siquiera hay que ejecutar el comando “mvn install” sobre el “proyecto-comun” para que tome los cambios, los toma automáticamente.

Que falta

De todas maneras existen algunos puntos sin resolver todavía:

  • No tenemos soporte para “mergear” el archivo web.xml, por lo que el web.xml del “proyecto-comun” va a ser pisado por el del “proyecto-nuevo”
  • Hay que tener cuidado de no crear clases en los mismos paquetes y con los mismos nombres, porque van a ser ignoradas (suponiendo que el application server le de prioridad a las clases del directorio “classes”)

Igualmente es una mejora substancial con lo que había antes, y permite tratar el código de presentación, prácticamente como si se tratase de una librería común, respetando su propio ciclo de vida, relacionado a las versiones, empaquetado, etc.