Leí sobre la utilidad watch and deploy (WAD) para realizar el redeploy de aplicaciones JEE de forma automática a distintos servidores al cambiar el código fuente.
Pruebas
A partir de aquí las pruebas realizadas con un proyecto de ejemplo. Para preparar el entorno se descarga el servidor wildfly, ejemplos de código y wad:
$ DIR=$HOME/workspace/pruebas-wad
$ mkdir -p $DIR && cd $DIR
$ wget 'https://download.jboss.org/wildfly/22.0.1.Final/wildfly-22.0.1.Final.tar.gz'
$ tar xf wildfly-22.0.1.Final.tar.gz
$ git clone --branch 22.x --depth 1 https://github.com/wildfly/quickstart.git
$ wget 'https://github.com/AdamBien/wad/releases/download/0.1.1/wad.jar'
Se realizaran las pruebas con el ejemplo quickstart/helloworld-rs
:
-
Prueba 1 - ejecución.
$ cd quickstart/helloworld-rs $ java -jar $DIR/wad.jar $DIR/wildfly-22.0.1.Final/standalone/deployments wad 0.1.1 command line argument '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' resulting deployment folders are: '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' WAD is watching ./src/main, deploying target/helloworld-rs.war to [/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments/helloworld-rs.war] [02:46:43]Exception in thread "main" java.lang.IllegalStateException: Maven application directory was not specified, and ${maven.home} is not provided in the system properties. Please specify at least on of these. at org.apache.maven.shared.invoker.MavenCommandLineBuilder.checkRequiredState(MavenCommandLineBuilder.java:126) at org.apache.maven.shared.invoker.MavenCommandLineBuilder.build(MavenCommandLineBuilder.java:61) at org.apache.maven.shared.invoker.DefaultInvoker.execute(DefaultInvoker.java:100) at com.airhacks.wad.control.Builder.build(Builder.java:41) at com.airhacks.wad.boundary.WADFlow.build(WADFlow.java:70) at com.airhacks.wad.boundary.WADFlow.buildAndDeploy(WADFlow.java:62) at com.airhacks.wad.boundary.WADFlow.<init>(WADFlow.java:42) at wad.App.main(App.java:75)
El error anterior es uno ya conocido aunque la solución de asignar la variable de entorno
MAVEN_HOME
no funcionó. En su lugar funciona establecer la propiedadmaven.home
al ejecutarwad.jar
. Dicho valor, en Debian, lo obtenemos haciendodpkg -L maven
y constatando que la mayoría de los archivos de maven se encuentran en el directorio/usr/share/maven
:$ java -jar -Dmaven.home=/usr/share/maven $DIR/wad.jar $DIR/wildfly-22.0.1.Final/standalone/deployments wad 0.1.1 command line argument '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' resulting deployment folders are: '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' WAD is watching ./src/main, deploying target/helloworld-rs.war to [/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments/helloworld-rs.war] [03:13:32][1]👍 built in 6358 ms Copying 6kB ThinWAR to (...)standalone/deployments/helloworld-rs.war 🚀 copied in 2 ms
-
Prueba 2 - nombre del directorio del proyecto es distinto al del war generado. Renombrando el proyecto y ejecutando wad:
$ cd $DIR $ mv quickstart/helloworld-rs{,-changed} $ cd quickstart/helloworld-rs-changed $ java -jar -Dmaven.home=/usr/share/maven $DIR/wad.jar $DIR/wildfly-22.0.1.Final/standalone/deployments wad 0.1.1 command line argument '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' resulting deployment folders are: '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' WAD is watching ./src/main, deploying target/helloworld-rs-changed.war to [/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments/helloworld-rs-changed.war] [03:19:27][1]👍 built in 6202 ms Exception in thread "main" java.lang.IllegalStateException: target/helloworld-rs-changed.war at com.airhacks.wad.control.Copier.copySingle(Copier.java:53) at com.airhacks.wad.control.Copier.lambda$copy$0(Copier.java:41) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at com.airhacks.wad.control.Copier.copy(Copier.java:41) at com.airhacks.wad.boundary.WADFlow.deploy(WADFlow.java:91) at com.airhacks.wad.boundary.WADFlow.buildAndDeploy(WADFlow.java:63) at com.airhacks.wad.boundary.WADFlow.<init>(WADFlow.java:42) at wad.App.main(App.java:75) Caused by: java.nio.file.NoSuchFileException: target/helloworld-rs-changed.war at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55) at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:149) at java.base/sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:99) at java.base/java.nio.file.Files.readAttributes(Files.java:1764) at java.base/java.nio.file.Files.size(Files.java:2381) at com.airhacks.wad.control.Copier.copySingle(Copier.java:47) ... 7 more
Ya que el problema anterior no tiene solución se vuelve el directorio al nombre anterior:
$ cd $DIR $ mv quickstart/helloworld-rs{-changed,}
-
Prueba 3 - incluir versión en el war generado. Para ello, se debe eliminar la linea
<finalName>${project.artifactId}</finalName>
del archivoquickstart/pom.xml
(superpom):$ sed -i.orig '/<finalName>${project.artifactId}<\/finalName>/d' quickstart/pom.xml $ cd quickstart/helloworld-rs $ java -jar -Dmaven.home=/usr/share/maven $DIR/wad.jar $DIR/wildfly-22.0.1.Final/standalone/deployments wad 0.1.1 command line argument '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' resulting deployment folders are: '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' WAD is watching ./src/main, deploying target/helloworld-rs.war to [/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments/helloworld-rs.war] [03:34:01][1]👍 built in 6314 ms Exception in thread "main" java.lang.IllegalStateException: target/helloworld-rs.war at com.airhacks.wad.control.Copier.copySingle(Copier.java:53) at com.airhacks.wad.control.Copier.lambda$copy$0(Copier.java:41) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at com.airhacks.wad.control.Copier.copy(Copier.java:41) at com.airhacks.wad.boundary.WADFlow.deploy(WADFlow.java:91) at com.airhacks.wad.boundary.WADFlow.buildAndDeploy(WADFlow.java:63) at com.airhacks.wad.boundary.WADFlow.<init>(WADFlow.java:42) at wad.App.main(App.java:75) Caused by: java.nio.file.NoSuchFileException: target/helloworld-rs.war at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55) at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:149) at java.base/sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:99) at java.base/java.nio.file.Files.readAttributes(Files.java:1764) at java.base/java.nio.file.Files.size(Files.java:2381) at com.airhacks.wad.control.Copier.copySingle(Copier.java:47) ... 7 more
Lo anterior no funciona ya que el war generado es:
$ find target/ -name '*.war' target/helloworld-rs-22.0.2.Final-SNAPSHOT.war
Al igual que el caso anterior este problema no tiene solución, por lo que debe volverse a agregar el tag
finalName
al archivopom.xml
:$ cd $DIR $ mv quickstart/pom.xml{.orig,}
Nota: este es un caso similar al anterior, ya que el war generado que se va a deployar no tiene el mismo nombre que el directorio del proyecto. Si se renombra el directorio
helloword-rs
ahelloworld-rs-22.0.2.Final-SNAPSHOT
wad funciona correctamente. -
Prueba 4 - workaround Se intenta crear un link simbólico al directorio del proyecto cuyo nombre corresponda al del artefacto que se generará, el cual incluye número de versión:
$ cd $DIR $ ln -s helloworld-rs quickstart/helloworld-rs-22.0.2.Final-SNAPSHOT $ cd quickstart/helloworld-rs-22.0.2.Final-SNAPSHOT $ java -jar -Dmaven.home=/usr/share/maven $DIR/wad.jar $DIR/wildfly-22.0.1.Final/standalone/deployments wad 0.1.1 command line argument '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' resulting deployment folders are: '/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments' WAD is watching ./src/main, deploying target/helloworld-rs.war to [/home/jmpc/workspace/pruebas-wad/wildfly-22.0.1.Final/standalone/deployments/helloworld-rs.war] [03:46:44][1]👍 built in 6364 ms Exception in thread "main" java.lang.IllegalStateException: target/helloworld-rs.war at com.airhacks.wad.control.Copier.copySingle(Copier.java:53) at com.airhacks.wad.control.Copier.lambda$copy$0(Copier.java:41) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at com.airhacks.wad.control.Copier.copy(Copier.java:41) at com.airhacks.wad.boundary.WADFlow.deploy(WADFlow.java:91) at com.airhacks.wad.boundary.WADFlow.buildAndDeploy(WADFlow.java:63) at com.airhacks.wad.boundary.WADFlow.<init>(WADFlow.java:42) at wad.App.main(App.java:75) Caused by: java.nio.file.NoSuchFileException: target/helloworld-rs.war at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55) at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:149) at java.base/sun.nio.fs.LinuxFileSystemProvider.readAttributes(LinuxFileSystemProvider.java:99) at java.base/java.nio.file.Files.readAttributes(Files.java:1764) at java.base/java.nio.file.Files.size(Files.java:2381) at com.airhacks.wad.control.Copier.copySingle(Copier.java:47) ... 7 more
Como se ve el programa está usando el nombre real del directorio (al que se apunta) y no el nombre del link simbólico, por lo cual no es posible el workaround propuesto.
Resumen de problemas encontrados
De las pruebas anteriores, los problemas encontrados fueron:
-
Escasa documentación en la página web, por lo menos en lo relacionado al error por falta de la property
maven.home
. El requerimiento de maven no es mencionado tampoco. -
El nombre del directorio donde está el proyecto debe tener el mismo nombre que el war generado por maven.
Lo último se debe a que leyendo el código fuente de wad este utiliza la api de maven-invoker, la cual no expone una forma de obtener el nombre del artefacto generado, por lo cual tiene sentido que se utilice el nombre del directorio como forma determinista de conocer el nombre del artefacto a deployar.
Conclusiones
Si bien la utilidad se ve interesante, se ve como una restricción importante el que el war generado deba tener el mismo nombre del directorio del proyecto y es una limitante que el workaround propuesto no funcione.
Quizás una alternativa interesante para evaluar sea entr.