lundi 2 août 2010

Accélérer le développement d'applications Vaadin avec Maven et Jetty

Cet article applique les principes décrits dans l'article "Accélérer le développement d'applications web Java avec Maven" aux applications web utilisant le framework Vaadin.


Présentation

Vaadin est un framework permettant de réaliser facilement des applications web riches. Il est construit sur le framework GWT.

Le principal avantage de Vaadin réside dans la génération des pages (ou écrans) de l'application. Ces derniers sont réalisés uniquement via du code Java, à la manière d'une interface Swing. Vaadin est packagé avec un ensemble de thèmes satisfaisant la plupart des besoins.


Objectif

On se propose d'accélérer le développement des applications utilisant Vaadin en mettant en place un rechargement dynamique des classes Java.

Comme dans le précédent article, ce tutoriel se focalisera sur l'utilisation de l'outil de build Maven conjointement au serveur d'application Jetty.


Etape 1 - Création du module Maven

Une fois de plus, la commande mvn archetype:generate se révèle très pratique pour mettre en route rapidement un projet Maven utilisant Vaadin.

$ mvn archetype:generate

Dans la liste des modèles de projet proposés, on note la présence du modèle "vaadin-archetype-clean". C'est ce dernier qui servira à générer un module de test Dans mon cas, il porte le numéro 7.

Choose a number : 7
Choose version : 1.3.0
Define value for property 'groupId': fr.pingtimeout
Define value for property 'artifactId': maven-vaadin
Define value for property 'version': 1.0-SNAPSHOT
Define value for property 'package': fr.pingtimeout

Le projet "maven-vaadin" est maintenant créé. Il contient une application basique utilisant Vaadin et affichant un bouton "Click Me".

On peut vérifier que le module contient bien les fichiers attendus.

$ cd maven-vaadin
$ tree.
|-- pom.xml
`-- src
    `-- main
        |-- java
        |   `-- fr
        |       `-- pingtimeout
        |           `-- MyVaadinApplication.java
        `-- webapp
            |-- META-INF
            |   |-- MANIFEST.MF
            |   `-- context.xml
            `-- WEB-INF
                `-- web.xml

Etape 2 - Activation du rechargement automatique

Cette fois, le plugin Jetty est déjà présent dans le fichier pom.xml. Toutefois, il doit être sensiblement modifié.

Dans le pom du module, le paramètre scanIntervalSeconds a pour valeur '0'. Un commentaire dans le fichier indique d'ailleurs que cette valeur désactive le rechargement automatique des classes.
Il faut donc changer la valeur du paramètre scanIntervalSeconds (par exemple, en spécifiant un scan toutes les secondes).

<scanIntervalSeconds>1</scanIntervalSeconds>

Etape 3 - Définition des ressources

Le chemin vers les ressources du projet sont définies par le paramètre code>resourcesAsCSV. Ce paramètre spécifie qu'elles sont situées dans le dossier /src/main/webapp et dans le dossier ${project.build.directory}/${project.build.finalName}. Dans mon cas, ceci équivaut au dossier /target/maven-vaadin-1.0-SNAPSHOT/.

Ce paramétrage pose un problème pour le rechargement automatique :

  • les classes recompilées sont situées dans le dossier ${project.build.outputDirectory} - dossier (1)
  • les classes initialement construites avec le war sont situées dans le dossier ${project.build.directory}/${project.build.finalName}/WEB-INF/classes/ - dossier (2)

En cas de modification d'un fichier .java, Jetty relance la compilation dans le dossier (1) mais n'en tient pas compte car les anciennes classes sont toujours dans le dossier (2).

Pour résoudre ce problème, il suffit de donner une nouvelle valeur au paramètre resourcesAsCSV :

<resourcesAsCSV>src/main/webapp,${project.build.directory}/${project.build.finalName}/WEB-INF/lib</resourcesAsCSV>

Seules les librairies de l'application seront désormais accédées en tant que ressources.

Etape 4 - Tests

Le serveur peut désormais être lancé via la commande :

$ mvn jetty:run

Premier lancement, premier échec. L'erreur suivante est générée par Jetty :

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Failed to configure plugin parameters for: org.mortbay.jetty:maven-jetty-plugin:6.1.25

Cause: Setter org.mortbay.resource.ResourceCollection.setResourcesAsCSV( java.lang.Class ) threw exception when called with parameter 'src/main/webapp,/home/pingtimeout/Projects/maven-vaadin/target/maven-vaadin-1.0-SNAPSHOT/WEB-INF/lib': java.lang.IllegalArgumentException: file://home/pingtimeout/Projects/maven-vaadin/target/maven-vaadin-1.0-SNAPSHOT/WEB-INF/lib is not an existing directory.

Contrairement au précédent tutoriel, il est obligatoire de spécifier la cible "package", faute de quoi Jetty ne peut pas trouver le dossier ${project.build.directory}/${project.build.finalName}/WEB-INF/lib, car ce dernier n'existe pas.


Lancer le serveur avec la commande :

$ mvn clean package jetty:run

Le serveur est correctement démarré, il est possible de consulter l'application à l'adresse :

http://localhost:8080/maven-vaadin/
.

[INFO] Started Jetty Server
[INFO] Starting scanner at interval of 1 seconds.

Aucune opération supplémentaire n'est requise pour que Jetty prenne directement en compte les modifications effectuées aux fichiers Java.

Modifier le fichier MyVaadinApplication.java pour y ajouter un bouton.

public void init() {
        window = new Window("My Vaadin Application");
        setMainWindow(window);
        window.addComponent(new Button("Click Me"));
        window.addComponent(new Button("Click Pingtimeout"));
}

Relancer une simple compilation des classes Java du projet

$ mvn compile

Des que le fichier est recompilé, Jetty recharge automatiquement les classes de l'application web.

[INFO] Restart completed at Mon Aug 02 14:04:51 CEST 2010

Rafraîchir le navigateur internet pour constater que la modification a été prise en compte.

Epilogue

Le plugin Jetty pour Maven se révèle d'une grande efficacité. Moyennant quelques paramètres, il est possible de lui faire recharger dynamiquement des classes Java dans des applications complexe (war avec de nombreuses librairies externes).

Des problèmes à la mise en place du plugin ? Des améliorations à apporter à ce tutoriel ? Voyons tout ça dans les commentaires !

Aucun commentaire:

Enregistrer un commentaire