Packaging maven rapide

on package l'application avec la commande suivante

$ mvn -Dmaven.test.skip=true clean compiler:compile war:exploded

  • -Dmaven.test.skip : saute l'exécution des tests
  • compiler:compile : compile le projets sans les tests (pour compiler aussi les tests ajouter compiler:testCompile et pour "tisser" l'AOP avec par exemple aspectj n'oubliez pas d'ajouter aspectj:compile !!!)
  • war:exploded (ou war:inplace) : ceci arrête le packaging de l'application au WAR éclaté (sans zipper l'arborescence éclatée dans un fichier WAR)

Script de déploiement rsync

La structure éclatée est ensuite déployée avec rsync. Si vous êtes sous Windows utilisez Cygwin et lancez votre script avec >sh monScript.sh.
J'utilise tomcat avec une structure multi-instance avec un déploiement par fichier de contexte XML à placer généralement dans le répertoire conf/Catalina/localhost
Un script s'impose (à adapter et améliorer en fonction des besoins).

Sous linux :
#!/bin/sh
JSERVER_USER=tomcat
HOST_DEPLOY=monserveur.mondomain.com
proj_name=monprojet
PROJ_HOME=~/workspace/$proj_name/target/$proj_name
TC_HOME=/srv/tomcat6
TC_INSTANCE=instance_monprojet
ssh ${JSERVER_USER}@${HOST_DEPLOY} "JAVA_HOME=/srv/java/jdk ${TC_HOME}/${TC_INSTANCE}/bin/catalina.sh stop"
mvn -Dmaven.test.skip=true clean compiler:compile war:exploded
time rsync -rzvt -e ssh --delete --progress ${PROJ_HOME}/* tomcat@${HOST_DEPLOY}:${TC_HOME}/webapps/$proj_name/
ssh ${JSERVER_USER}@${HOST_DEPLOY} "JAVA_HOME=/srv/java/jdk ${TC_HOME}/${TC_INSTANCE}/bin/catalina.sh start"


Evidemment, il faudra copier sa clé publique SSH dans /home/tomcat/.ssh/authorized_keys pour que les commandes d'arrêt et de démarrage du serveur Tomcat soient exécutées de façon transparente sans avoir à entrer les mots de passe à chaque fois. La commande ssh-copy-id (du moins sous Debian) est appropriée. Sinon faire la copie à la main de votre clé publique dans l'authorized_keys du serveur.

Sous windows, si votre disque est par exemple D:,remplacez la ligne PROJ_HOME par
PROJ_HOME=/cygdrive/d/workspace/$proj_name/target/$proj_name

Que fait ce script de déploiement ?
  1. il arrête le serveur d'application distant grâce à SSH
  2. il compile et package l'appli avec Maven (sur le poste de développement)
  3. il synchronise l'arborescence éclatée avec l'arborescence distante de l'application; l'option --delete de rsync est importante car elle permet d'éliminer les fichiers sur le serveur distant qui ont pu être supprimés lors des modifications précédentes sur le code (suppressions de classe, de librairie etc.)
  4. il redémarre le serveur d'application
Cette méthode présente plusieurs avantages :
  1. si vous êtes derrière une ligne ADSL pour déployer vers un serveur distant, vous gagnerez un temps précieux pour uploader votre application (upload parfois 100 fois supérieur puisque rsync ne transfère que les modifications entre fichiers); en effet, vos librairies JAR ne changent pas beaucoup une fois le projet initié et rsync verra qu'il n'y a pas besoin de les redéployer... évidemment pour chaque nouveau fichier, le premier upload sera coûteux...
  2. le déploiement est propre car ceci arrête le serveur avant le déploiement; le déploiement à chaud sur Tomcat entraîne généralement le bien connu "OutOfMemoryError : PermGen Space"; certains diront que cette erreur peut être évitée ( http://jroller.com/agileanswers/entry/preventing_java_s_java_lang ) mais parfois, on a pas le choix...
  3. les tâches sont toutes automatisées et le temps de déploiement est sérieusement optimisé : -30% sur le packaging (x5 s'il n'y a pas à faire de clean sur le projet), x10 à x100 sur le déploiement et votre serveur n'a pas besoin de dézipper le WAR (en prime vous gagnez de l'espace puisque vous n'avez plus de WAR sur le serveur cible)...
  4. le scripting apporte une flexibilité accrue notamment si vous avez à déployer sur plusieurs instances et/ou serveurs à la fois dans le cadre d'un cluster. Les options rsync permettent aussi d'exclure des fichiers que vous ne voulez pas ou plus déployer, mais attention : ceci peut être dangereux pour votre application si vous excluez des fichiers et que vous oubliez ensuite qu'il faille les déployer de nouveau...

Conclusion

Dans cet exemple le déploiement est fait directement entre le poste de développement et le serveur. Il se peut qu'en entreprise lorsque vous travaillez à plusieurs sur le serveur distant, que ce dernier ait accès à un repository Subversion ou GIT. Dans ce cas il suffit d'adapter le script pour qu'il se trouve sur le serveur et que ce soit lui qui récupère des sources par SVN (qui fonctionne par différence tout comme rsync!). Le script récupère alors les sources, construit le projet, arrête le serveur d'appli (ou l'application), déploie, redémarre le serveur d'appli (ou l'application).
Si l'on est dans un process d'intégration continue, on peut par exemple utiliser Hudson auquel on fournira un script shell réduit au déploiement (installer un plugin d'opération post-build), le build étant gérée par Hudson en lui fournissant les options maven.

Pour plus d'infos : http://maven.apache.org/plugins/maven-war-plugin/