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 »


8 commentaires sur “Environnement de développement Maven/Eclipse pour GWT 1.7”

  • Attention, utiliser des variables d'environnement dans un pom n'a pas l'air de fonctionner dans eclipse avec le plugin m2eclipse (issue ouverte : http://jira.codehaus.org/browse/MNGECLIPSE-581)
  • Pourquoi utiliser des variables d'environnements ? Les profiles maven peuvent être activée en fonction de la famille de l'os utilisé (project>profiles>profile>activation>os) et ... Merci pour ce tuto !
  • Oui, mais non :-) Les profils de maven peuvent être automatiquement activés en fonction de l'os, tant qu'on utilise pas de profils non activés automatiquement (en tout cas avec maven 2.0.9). En résumé, il n'est pas possible d'utiliser des profils à activation auto et des profils avec mvn -PmonBeauProfil. Or dans notre application, nous avons besoin de profils, autre que ceux que l'on active automatiquement. Nous avons donc supprimés nos profils activés automatiquement que nous utilisions au début pour provisionner la variable, pour utiliser une variable d'environnement. Snif :-) Si vous n'avez pas besoin de profils, vous pouvez effectivement supprimer la dépendance sur la variable d'environnement PLATFORM avec quelque chose du genre :
        
            
                gwt-dev-windows
                
                    windows
                
                
                    true
                    
                        windows
                    
                
            
            
                gwt-dev-mac
                
                    mac
                
                
                    false
                    
                        mac
                    
                
                    
            
                gwt-dev-linux
                
                    linux
                
                
                    false
                    
                        linux
                    
                
            
        
    
  • Sauf erreur de ma part, cela fonctionne avec Maven 2.1.0 (que j'utilise en temps normal) et avec Maven 2.0.9
    
      4.0.0
      org.example
      test
      jar
      1.0-SNAPSHOT
      test
      http://maven.apache.org
      
        
          junit
          junit
          3.8.1
          test
        
      
      
        
        
          monBeauProfil
        
        
        
          linux-platform
          
            false
            
              linux
            
          
        
      
    
    
  • Autant pour moi, mes souvenirs étaient mauvais. Le problème était qu'on ne peut pas activer un profil par défaut en permanence et un profil activé par défaut par quelque chose comme l'os. Dans ton exemple, si tu ajoutes dans le profil monBeauProfil
    true
    et que tu lances mvn help:active-profiles, seul le profil linux-platform est actif. C'est un bug de maven il me semble, à confirmer.
  • Petit récapitulatif sur l'utilisation des profiles dans Maven. * Un profil déclaré comme "activebydefault" veut dire que si il n'y a AUCUN autre profil maven d'activé dans le build alors ce dernier dois l'être. En clair le cas d'utilisation est super rare. * Les règles d'activation d'un profil ne sont pas héritées. De ce fait si vous déclarez un profil "toto" dans le pom principal d'un projet et que vous utilisez ce même profil dans un sous module. Si vous lancez le build au niveau du pom parent maven va voir la condition d'activation et activer les deux spécificités du profil dans le parent et le module. Si vous lancez le build directement depuis le sous-module, Maven ne verra pas la règle d'activation et n'utilisera pas ce profil. * (Depuis maven 2.0.10 si ma mémoire est bonne) Tout profil "toto" peut être activé par -Ptoto et désactivé par -P!toto ou -P-toto quelque soit les règles d'activation. * Perso je préfère ne pas trop jouer avec des règles multiples d'activation/desactivation des profils. Pour les profils par défaut, dans le sens ou je veux qu'ils soient toujours activés sauf si je leur demande de pas l'etre je fais qquechose comme :
         
         enforce
         
           
             !skip-enforce
           
         
       
     
  • Merci pour cet article très intéressant, ca lecture a été comme une délivrance pour moi ;). Je viens du monde c++, et j'avais bien du mal a y comporendre tous les tenants et aboutissants, entre gwt, maven et le hosted mode via eclipse. J'ai réorganisé mon projet GWT en suivant vos recommandations, et tout me parait clair a présent.
  • L'article est interessant mais devrait être mis au gout du jour suite à GWT 2.0 Notamment le gwt-dev ne nécessite plus de classifier lié à l'OS.
    1. Laisser un commentaire

      Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha