Nov 07

Plugin de maven para cambio de versiones en los pom.xml

 

Hace tiempo que tengo una necesidad en el trabajo y que he ido dejando olvidada por falta de tiempo. Cuando en maven manejas proyectos grandes, cada uno con varios subproyectos  y encima esos proyectos grandes dependen de otros proyectos grandes que también tienen sus subproyectos, llevar un versionado en condiciones de cada jar puede ser un infierno.

Me explico, tu proyecto grande lleva un fichero pom.xml. Cada uno de los subproyectos también. En los demás proyectos también y en sus subproyectos también. Algunos de los jar de alguno de esos subproyectos pueden ser librerías básicas, por ejemplo, una librería de componentes swing o de utilidades para acceso a base de datos, de gráficos, o lo que sea. Aparecen dependencias de esa librería en los pom.xml de muchos de los proyectos y subproyectos.

¿Qué pasa si cambiamos la versión de esa librería?. Que no queda más remedio que ir en todos los proyectos y subproyectos en los que queremos actualizar la versión buscando dicha librería por los pom.xml y cambiando el número de versión. Desde luego, una tarea rutinaria, pero algo aburrida, que lleva un tiempo y susceptible de error "humano" al hacerla a mano.

Así que pensé en hacer un script o algo que buscara por los pom.xml y cambiara automáticamente las versiones que se le dijeran. Así que por fin me puse a ello y como siempre, para jugar y aprender algo nuevo, en vez de un script, decidí hacerlo como plugin de maven.

El resultado es un plugin de maven con dos goals:

  • lista saca en un fichero un listado de todos los artifacts que aparecen en el pom.xml del proyecto y subproyectos actuales y con la nueva versión o groupId que queremos para cada sub/proyecto. Ese fichero lo utilizará el siguiente goal para hacer los cambios en el pom.xml.
  • cambia realiza los cambios indicado en el fichero anterior en todos los pom.xml que encuentre del proyecto y subproyecto. 
    • Si se ejecuta este goal en el mismo proyecto en que se ejecutó el lista, obtenemos un cambio de versión en el proyecto. Quizás el plugin release de maven hace esto mismo y mejor.
    • Si se copia el fichero de cambios en otros proyecto distinto y ejecutamos allí el goal cambia, conseguimos cambiar la versión de las dependencias con el primer proyecto.

Lo he estado usando ya y probando, va bastante bien, aunque veo que el uso no es demasiado intuitivo, siempre se me olvida hacer alguna cosa.

Ahí van un par de enlaces:

Aprender, pues aprendí algunas cosillas, sobre todo, ¿cómo no?, problemas con los que me he tropezado. El más gordo ha sido que no hay forma de hacer un deploy de un plugin en condiciones. En el pom.xml del plugin, el packaging es "maven-plugin". Pues el deploy no sabe hacer un deploy de una cosa cuyo packaging es "maven-plugin", así que para que funcione el deploy, debes poner packaging "jar". Pero claro, eso sube el fichero .pom al repositorio remoto con ese packaging que no es, así que luego, a mano y en el repositorio remoto, tienes que cambiar el "jar" por "maven-plugin" otra vez. Y el problema sigue, ya que al cambiar eso a mano, los ficheros de checksum/huella o como quieras llamarle .md5 y .sha1 que se crean en el repositorio remoto ya no cuadran y al bajarte el plugin con maven dan un warning.

Y yo creo que ya está bien de proyectos. Esta tarde me dedicaré a otra cosa.

Nov 04

maven, jar, assembly y snapshots (II)

 

Bueno, pues después de compilar el maven-assembly-plugin, lo he intentado en el trabajo y me has pasado las siguientes cosas:

Hago el mvn install. Me pide uno de los jar que mencioné en el post anterior. Le hago a ese jar el mvn install:install-file para instalarlo a mano. Sigo compilando y no me pide el segundo. Sin embargo, fallan los test de compilado.

Vuelvo a recompilar sin pasar los test   ( mvn -Dmaven.test.skip=true install ) y compilado, sin test. Me pongo a ejecutar el mvn assembly:assembly en un proyecto … y excepción, class not found de una de las clases del plugin

Después de pelearme, buscar ese class not found a ver de dónde es para poner la dependencia y desesperarme un rato gordo, se me ocurre hacer el mvn install:install-file del segundo jar mencionado en el post anterior. Cosa curiosa, aunque ese mismo jar me lo bajó maven de algún repositorio, y aunque el número de versión coincide, no es el mismo. Con este segundo jar ya compila todo pasando los test y no da excepción en el mvn assembly:assembly. Supongo que este tipo de cosas es lo que tiene el tirar de versiones beta-SNAPSHOT. De todas formas, también deja claro que no son demasiado cuidadosos con los jar que suben a internet, ya que con el mismo número de versión parece que puedes encontrar versiones distintas.

Y al final resulta que no funciona. Efectivamente, el mvn assembly:assembly te mete en el zip las versiones snapshots de los jar de los que dependes sin poner la fecha y manteniendo la palabra snapshot …. simpre y cuando en tu repositorio local hayas hecho un mvn install de ese snapshot con fecha posterior a la más moderna del repositorio de snapshot. O sea, que para que funcione, tienes que sacar el cvs de todos los proyectos snapshot de los que dependes y hacer mvn install de todos ellos y rezar porque nadie suba una snapshot al repositorio común en el entretanto.

En fin, estoy planteándome hacer un plugin que llame a assembly:directory. Este goal deja todos los ficheros en el target, desempaquetados. Luego, mi plugin, cambiará los ficheros-fecha.jar por fichero-snapshot.jar y hará el zip. Este bug lleva ya al menos un año en la página de bugs y todavía da la impresión de que no tiene una corrección seria.

Se me ocurrió mirar a mi los fuentes del plugin assembly a ver si podía hacer un arreglo…. pero de svn se baja la friolera de unos 6000 ficheros en los que hay 286 ficheros fuente java. No sé, creo que me da un poco de pereza….

Jun 19

assembly, jar y snapshot incompatibles en maven

Me he vuelto a tropezar con un pequeño problema que esta vez, tampoco he conseguido resolver.

Con maven damos a los proyectos un número de versión, de forma que luego el jar generado lleva dicho número de versión. Así, por ejemplo, podemos tener un proyecto MiProyecto al que decimos a maven que es versión 1.0 y  maven generará un jar MiProyecto-1.0.jar. Mientras estamos desarrollando este proyecto, podemos decir a maven que es una versión "SNAPSHOT", de esta forma sabe que ese jar se va a generar muchas veces y que será posiblemente distinto cada vez. Al hacerlo así, maven genera el jar añadiendo la fecha y hora del compilado, tal que así: MiPoryecto-1.0-20080619-131234.jar.

Esto tiene una ventaja adicional. Si hacemos ahora otro proyecto que depende de la versión SNAPSHOT de MiProyecto, cada vez que compilemos este nuevo proyecto, maven buscará si hay un jar más moderno de MiProyecto y se lo bajará. De esta forma, sin nosotros molestarnos en actualizar el jar, nuestro nuevo proyecto siempre tendrá disponible la última versión snapshot de MiProyecto

A maven también podemos decirle que nos genere el fichero de manifiesto dentro de nuestro jar principal y podemos decirle que automáticamente ponga el Class-Path con todos los jar que necesite. Maven lo hace correctamente y pone en esta dependencia un MiProyecto-1.0-SNAPSHOT, así exactamente, con todas las letras y sin reemplazar SNAPSHOT por ninguna fecha.

Finalmente, hay un plugin de maven llamado assembly que permite meter automáticamente en un zip nuestro jar, nuestros ficheros de configuración y todos los jar de los que dependemos. De esta forma, eso sería un zip de distribución que, entregándoselo a otra persona, podría simplemente desempaquetarlo donde quisiera y ejecutar nuestro programa teniendo todo lo necesario.

Pues bien, este plugin assembly no está de acuerdo con lo del manifiesto del jar. El plugin assembly, al generar el zip, mete dentro la versión snapshot de mi proyecto con MiProyeto-1.0-20080619-131234.jar, con todas las fechas y horas habidas y por haber. Nuestro jar principal busca MiProyecto-1.0-SNAPSHOT.jar y claro, no lo encuentra.

Buscando y rebuscando, al final encuentro que es un bug de uno de los dos, bien de maven al generar el manifiesto, bien de assembly al guardar el jar de MiProyecto. Así que de momento me he auto-prohibido generar zips que dependan de snapshots.