JRebel, le redéploiement c'est à chaud !


Quand on développe des applications web Java EE, on passe généralement son temps à redéployer son application et redémarrer son conteneur… Heureusement on peut compter depuis un moment sur JRebel pour grandement augmenter sa productivité lors des développements en permettant le rechargement à chaud des modifications de façon plus poussé que le Hot Swap intégré à la JVM.

Fonctionnement

JRebel est un agent java qui va surveiller les modifications de notre application et les appliquées au sein de la JVM à chaud. Pour celà, l’agent va scanner le classpath à la recherche de fichiers rebel.xml décrivant les ressources à surveiller.

Installation

La documentation de JRebel met l’accent sur l’intégration avec les IDE (Eclipse, IntelliJ Idea, Netbeans, MyEclipse) et est très bien faite : JRebel IDE Plugins Personnellement j’utilise rarement les fonctionnalités de déploiement intégrés dans les IDE (peut-être à cause de wtp dans Eclipse…) et préfère utilisé un serveur embedded (dans un plugin Maven par exemple) ou même directement le serveur d’application installé sur mon poste.

On a donc besoin de télécharger une archive de JRebel, disponible ici : Télécharger JRebel

Une fois dezippé, il faut exécuter la configuration de JRebel via bin/jrebel-config.{cmd|sh} et suivre les instructions de l’assistant. Pour ajouter l’agent JRebel à la JVM : -noverify -javaagent:$JREBEL_HOME/jrebel.jar

Configuration de votre application

Il faut maintenant s’intéresser à la génération des fichiers de configuration rebel.xml. Il existe un plugin Maven pour faire le travail à notre place : http://zeroturnaround.com/software/jrebel/maven/

<plugin>
    <groupId>org.zeroturnaround</groupId>
    <artifactId>jrebel-maven-plugin</artifactId>
    <version>1.1.3</version>
    <configuration>
        <classpath>
            <resources>
                <resource>
                    <includes>
                        <include>com/github/jcgay/**</include>
                    </includes>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                </resource>
            </resources>
        </classpath>
    </configuration>
    <executions>
        <execution>
            <id>generate-rebel-xml</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Le plugin se base sur le type de votre module pour générer la configuration par défaut (pour par exemple intégrer src/main/webapp aux ressources surveillées). Ce comportement peut-être surchargé si par exemple votre webapp utilise le type maven jar en utilisant war au sein de la configuration du plugin. Le plugin fonctionne très bien au sein des projets multi-module. On peut filtrer avec des include/exclude les ressources à intégrer dans le rechargement de JRebel.

Les chemins générés au sein de la configuration sont absolus par défaut (donc spécifique à votre environnement), il est possible de variabiliser les chemins générés pour les rendre relatifs. Je n’ai jamais utilisé la fonctionalité (je ne package pas la configuration JRebel dans mes artifacts finaux) mais c’est toujours bon à savoir.

Toutes les possibilités de configuration du rebel.xml sont décrites ici : documentation rebel.xml

Vérification du fonctionnement

Si l’agent est correctement configuré, on obtient au lancement de la JVM :

[2013-01-25 16:16:04] #############################################################
[2013-01-25 16:16:04] 
[2013-01-25 16:16:04]  JRebel 5.1.1 (201211271929)
[2013-01-25 16:16:04]  (c) Copyright ZeroTurnaround OU, Estonia, Tartu.
[2013-01-25 16:16:04] 
[2013-01-25 16:16:04]  Over the last 30 days JRebel prevented 
[2013-01-25 16:16:04]  at least 95 redeploys/restarts saving you about 3.9 hours.
[2013-01-25 16:16:04] 
[2013-01-25 16:16:04]  This product is licensed to ******
[2013-01-25 16:16:04] 
[2013-01-25 16:16:04]  The following plugins are disabled at the moment: 
[2013-01-25 16:16:04]  * Click plugin (set -Drebel.click_plugin=true to enable)
[2013-01-25 16:16:04]  * JRuby Plugin (set -Drebel.jruby_plugin=true to enable)
[2013-01-25 16:16:04]  * Jersey plugin (set -Drebel.jersey_plugin=true to enable)
[2013-01-25 16:16:04]  * Oracle ADF Core plugin (set -Drebel.adf_core_plugin=true to enable)
[2013-01-25 16:16:04]  * Oracle ADF Faces plugin (set -Drebel.adf_faces_plugin=true to enable)
[2013-01-25 16:16:04]  * RESTlet plugin (set -Drebel.restlet_plugin=true to enable)
[2013-01-25 16:16:04]  * Seam-Wicket plugin (set -Drebel.seam_wicket_plugin=true to enable)
[2013-01-25 16:16:04]  * Spring Data Plugin (set -Drebel.spring_data_plugin=true to enable)
[2013-01-25 16:16:04]  * WebObjects plugin (set -Drebel.webobjects_plugin=true to enable)
[2013-01-25 16:16:04] 
[2013-01-25 16:16:04] #############################################################

Puis les ressources qui sont surveillées :

[2013-01-25 16:16:06] JRebel: Directory '/home/jcgay/dev/app/target/classes' will be monitored for changes.
[2013-01-25 16:16:06] JRebel: Directory '/home/jcgay/dev/app/src/main/webapp' will be monitored for changes.
[2013-01-25 16:16:06] JRebel: Directory '/home/jcgay/dev/app/src/main/resources will be monitored for changes.

Les classes seront maintenant rechargées dès qu’elles sont compilées depuis l’IDE (pour peu que celui ci soit bien configuré pour compiler les classes au même endroit que Maven).

Les ressources sont rechargées après un hit sur le serveur d’application. Pour chaque ressource rechargée, une entrée est loggée :

[2012-12-20 11:33:56] JRebel: Reloading class 'com.github.jcgay.app.Person'.

Notes

  • La génération de la configuration via le plugin Maven est liée à la phase “generate-resources”. Il est possible que le reste du build écrase cette configuration (par exemple de l’overlay de war, ou du tissage d’aspect à partir du build d’un war dans ses modules). Génaralement dans ce cas je change la phase d’exécution du plugin Maven pour une phase postérieure à celle qui pose problème…
  • Attention à bien cocher “I use Maven to build my application” dans l’assistant de configuration de JRebel, sinon vous verrez surement le monitoring de plugin JRebel correctement s’activé mais pas celui des ressources de l’application.
  • Dans IntelliJ Idea, pour que la compilation se fasse bien dans le même répertoire que Maven, il faut cocher “Use Maven output directories”.
  • Toujours dans Idea, si l’on utilise le debugger, celui si se retrouvera désynchronisé dès la prise en compte d’un rechargement à chaud. Dans ce cas il faut installer le plugin JRebel, et ajouter la propriété -Drebel.debugger_integration=true au lancement de la JVM.

comments powered by Disqus