Environnement de développement Maven/Eclipse pour GWT 1.7

Développer, tester et exécuter des applications GWT est facile avec le plugin "GWT for Eclipse". Mais ce plugin n’est pas vraiment adapté pour Maven2, l’arborescence de dossiers qu’il requiert n’étant pas conforme au standard des applications web buildées avec Maven.

Aujourd'hui, nous allons nous concentrer sur le développement et l'exécution d'application GWT via Maven et Eclipse. Les tests seront couverts dans un autre article, à paraître prochainement.

Arborescence du projet attendue par GWT :

+ src module.gwt.xml

  • war
    • css
    • img
    • WEB-INF
      • classes
      • lib web.xml module.html

Arborescence du projet attendu par Maven :

+ src + main + java + resources + public + css + img module.gwt.xml + webapp + WEB-INF web.xml module.html

Après avoir mis en place des environnements de développement sur un projet réel, voici les deux solutions qui nous paraissent les plus pertinentes. Les objectifs de notre environnement de développements sont :

  • Simplicité : peu de choses spécifiques à installer
  • Garder une arborescence de dossier conforme au standard Maven
  • Exécuter / déboguer l’application dans son ensemble en Hosted Mode à partir d’Eclipse, en un click
  • Exécuter l’application en standalone via le plugin maven jetty
  • Générer automatiquement les classes de services Asynchrones et d’i18n
  • Limiter au maximum les générations de fichiers par GWT hors arborescence Maven

Chacune de ces deux solutions est illustrée dans un projet java dont les sources sont mises à disposition ici et .

État des lieux

Deux plugins Maven2 ont été développés pour GWT. maven-googlewebtoolkit2-plugin hébergé chez Google et gwt-maven-plugin par Codehaus. Finalement, les deux ont fusionné et les efforts de développement sont maintenant concentrés sur le second.

Le plugin Codehaus permet :

  • d'invoquer le compilateur GWT lors du build Maven
  • de déboguer une application GWT en Hosted Mode
  • d’exécuter les tests unitaires GWT
  • de générer les classes de services asynchrones et d’internationalisation

Par ailleurs, les concepteurs de GWT estiment que l’exécution et le débogage d’applications GWT en Hosted Mode doit se faire en mode "light", uniquement pour tester l'IHM. C'est pourquoi le Hosted Mode de GWT cherche un deuxième fichier web.xml, dédié au débogage, différent du fichier web.xml principal de l'application. Ce mode de fonctionnement, pratique dans le cas où une seule l’interface web est à tester en Hosted Mode, s’avère très contraignant dès lors que l’on veut tester l’intégralité de l’application, communications client/serveur comprises. De plus, dans un projet Maven standard, il n'y a qu'un seul fichier web.xml... On souhaiterait donc pouvoir exécuter et déboguer dans Eclipse en utilisant le Hosted Mode et le fichier web.xml standard de Maven.

Après pas mal de recherches et d'essais, nous avons identifiés 2 configurations viables. Les voici avec leur avantages et inconvénients.

Configuration Maven commune à chaque configuration :

<properties>
   <gwt .version>1.7.0</gwt>
</properties>

<dependencies>
   <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-user</artifactid>
      <version>${gwt.version}</version>
   </dependency>
   <dependency>
      <groupid>com.google.gwt</groupid>
      <artifactid>gwt-servlet</artifactid>
      <version>${gwt.version}</version>
   </dependency>
</dependencies>

<plugins>
   <plugin>
      <groupid>org.codehaus.mojo</groupid>
      <artifactid>gwt-maven-plugin</artifactid>
     <configuration>
         <module>com.octo.gwt.FirstModule</module>
         <runtarget>com.octo.gwt.FirstModule/FirstModule.html</runtarget>
         <i18nmessagesbundle>com.octo.gwt.client.i18n.Messages</i18nmessagesbundle>
      </configuration>
      <executions>
         ...
               <goal>compile</goal>
               <goal>i18n</goal>
               <goal>generateAsync</goal>
          ...
      </executions>
   </plugin>
</plugins>

De cette manière, le plugin est configuré pour compiler le projet et générer automatiquement les classes de services asynchrones et d'internationalisation lors de la génération des sources.

L’application est exécutable dans jetty via la commande mvn jetty:run-war. Reste à réussir à l'exécuter / déboguer dans Eclipse via le Hosted Mode.

1ère solution viable : intégration avec le plugin Eclipse

Pour améliorer la productivité des développements GWT, Google fournit un plugin GWT for Eclipse.

Le plugin Maven permet de générer un fichier .launch (commande mvn gwt:eclipse) propre à chaque module GWT, qui est alors exécutée par le plugin GWT for Eclipse. Cela permet de lancer l'application et de la déboguer simplement dans l'IDE.

Il sera toutefois nécessaire de configurer l’application comme étant un projet "Google" dans Eclipse, soit directement via l'IDE (bouton droit sur le projet, "Google", "Web Toolkit Settings" et spécifier le SDK GWT à utiliser), soit en configurant le plugin maven-eclipse comme cela a été fait dans le pom.xml du projet d'exemple.

Des problèmes de sécurité lors de la sérialisation / dé-sérialisation d'objets lors des appels GWT-RPC peuvent se produire. Il faudra d’abord veiller à rajouter l’url de chaque servlet nécessaire dans les fichiers de configuration de module .gwt.xml, en plus de la déclaration dans le fichier web.xml. Exemple :

<servlet path="/firstService" class="com.octo.gwt.server.FirstServiceImpl" />

Pour exécuter et déboguer l'application, il suffit alors de faire un ou un Debug As.. sur le fichier .launch.

Avantages de la configuration "Plugin GWT for Eclipse"

  • Exécution et débogage simple via le fichier .launch et le plugin Eclipse

Inconvénients de la configuration "Plugin GWT for Eclipse"

  • Génération d'un répertoire /war dans la racine du projet, non conforme à l'arborescence maven, non supprimé par un mvn clean
  • Nécessité d'installer un SDK GWT complet sur le poste de développement
  • Obligation de déclarer toutes les servlets nécessaires dans les fichiers gwt.xml en plus du fichier web.xml

2ème solution viable : utilisation d'une classe de lancement

Dans la première solution, il est nécessaire d'installer les SDK GWT, alors qu'en fait ceux-ci sont déjà récupérés par Maven et sont donc présents dans le repository local.

Nous avons donc développé une petite classe Java qui permet de lancer directement le projet en Hosted Mode, sans utiliser le plugin GWT for Eclipse, en utilisant les classes GWT via le classpath de Maven. Cette classe (Launcher.java), dont le code est disponible dans les sources du projet : src/test/java/Launcher.java. Elle se base sur la configuration du plugin Maven GWT dans le pom.xml pour obtenir les données de configuration nécessaires au lancement de l'application en Hosted Mode.

Une donnée de configuration supplémentaire est nécessaire pour le plugin :

<plugin>
      <groupid>org.codehaus.mojo</groupid>
      <artifactid>gwt-maven-plugin</artifactid>
      <configuration>
          .....     
          <hostedwebapp>target/hostedWebapp</hostedwebapp>
      </configuration>
</plugin>

Pour le bon démarrage de l'application GWT, la classe Launcher recopie l'ensemble du répertoire Maven standard "src/main/webapp/" dans target/hostedWebapp avant de démarrer l'application, ce qui nous affranchi des problèmes de sécurité lié à la sérialisation. Il n'y a donc pas besoin d'ajouter les balises dans les fichiers de configuration des modules GWT. Et nous pouvons travailler avec le fichier web.xml réel de l'application...

Il est par contre nécessaire d'ajouter dans les dépendances du projet gwt-dev, qui contient le Hosted Mode :

<dependency>
   <groupid>com.google.gwt</groupid>
   <artifactid>gwt-dev</artifactid>
   <version>${gwt.version}</version>
   <classifier>${env.PLATFORM}</classifier>
   <scope>provided</scope>
</dependency>

La librairie gwt-dev étant dépendante du système d'exploitation, il est nécessaire de rajouter la variable d'environnement PLATFORM avec la valeur corresponde au jar à utiliser. (SET PLATFORM=windows, export PLATFORM=linux ou export PLATFORM=mac)

Pour que GWT trouve le code source des classes de l'interface web, il faudra ajouter les répertoires "src/main/java" et "target/generated-sources/gwt" dans le classpath d'exécution de la 'Run configuration' d'Eclipse.

Avantages de la configuration "utilisation d'une classe de lancement"

  • Simplicité d'installation : ne requiert pas de SDK GWT ni de plugin Eclipse
  • Totale conformité aux standards Maven
  • Exécution et débogage en Hosted Mode via une simple classe java avec une méthode main()
  • Indépendance vis à vis de l'IDE utilisé

Inconvénients de la configuration "utilisation d'une classe de lancement"

  • Première prise en main relativement complexe
  • Dépendance vers l'OS via une variable d'environnement

En conclusion

Ces solutions ne sont pas parfaites. Elles sont cependant les meilleures que nous ayons trouvées compte tenu des différentes contraintes imposées par GWT.

Dans le cadre de notre projet GWT, nous avons opté pour la seconde solution pour sa simplicité d'utilisation. Configurer un environnement de développement pour le projet ne nécessite plus qu'un IDE et Maven. Dans le cas où l'équipe de développement serait déjà familière avec le Plugin GWT for Eclipse et souhaite passer à Maven, la première solution sera sans doute plus pertinente.

Il est à espérer que GWT 2.0 respectera plus les standards Maven, notamment en terme d'organisation de fichiers, afin de faciliter la mise en place d'environnement de développement industriel dédiés à GWT.

PS : l'ensemble de cet article s'applique à GWT 1.7. Il devrait aussi s'appliquer à GWT 1.6. GWT 1.5 utilisant Tomcat à la place de Jetty, certains détails peuvent changer. Les grands principes sont cependant transposables.

_

Guide pour tester les sources en 5 minutes

Pré requis :

- Avoir Java et Maven installés, avec la commande mvn disponible dans le PATH de l'OS - Avoir Eclipse installé (du moins pour la configuration Plugin GWT for Eclipse) - Télécharger les sources des deux projets d'exemple : demo-gwt-plugin et demo-gwt-launcher.

Configuration "Plugin GWT for Eclipse" :

  • Installer le plugin Eclipse et le SDK GWT 1.7 via l'update site (http://dl.google.com/eclipse/plugin/3.5)
  • Ouvrir une invite de commande et se placer dans le répertoire du projet demo-gwt-plugin
  • mvn eclipse:eclipse : génération des fichiers .project et .classpath customisés pour le plugin Google
  • mvn gwt:eclipse : génération du dossier /war et du fichier .launch à la racine du projet
  • Importer le projet dans Eclipse
  • Bouton droit sur le fichier com.octo.gwt.FirstModule.launch : "Run As.." google FirstModule

Configuration "utilisation d’une classe de lancement" :

  • Ouvrir une invite de commande et se placer dans le répertoire du projet demo-gwt-launcher
  • Ajouter la variable d'environnement "PLATEFORM" avec la valeur nécessaire pour rappatrier le jar GWT-dev spécifique à l'OS - Pour Windows : set PLATFORM=windows - Pour Linux : export PLATFORM=linux - Pour Mac : export PLATFORM=mac
  • mvn eclipse:eclipse
  • Importer le projet dans Eclipse
  • Créer une configuration "Java Application" via "Run / Run Configurations.." : - Sélectionner le projet demo-gwt-launcher et la Main class src/test/java/Launcher.java - Spécifier l'argument VM -Xmx512M pour éviter les OutOfMemoryExceptions - Ajouter dans le classpath de lancement les dossiers src/main/java et target/generated-sources/gwt du projet - Cliquer sur "Run"

_