Faire collaborer gwt-maven-plugin, m2e (Maven) et Google Plugin (GWT)

D’après moi, un seul plugin aurait suffit : gwt-maven-plugin. Mais il en existe d’autres, notamment m2e (Maven 2 pour Eclipse) et GPE (Google Plugin Eclipse).
La problématique de ce billet n’est pas de dire si ils sont bien ou pas, mais de fournir une méthode pour utiliser les trois ensemble de manière complémentaire et sans qu’ils entrent en conflit.

1. Préambule
2. Génération du projet
3. Description du contenu généré et nettoyage
4. Lancement du projet dans un navigateur
5. Conclusion

haut

1.Préambule

Pour l’installation de ces plugins, je recommande de partir d’un Eclipse tout neuf téléchargeable ici, puis de suivre les procédure d’installation de m2e et de GPE.

haut

2. Génération du projet

Dans Eclipse, créer un nouveau projet Maven.
generation-01
Dans la première fenêtre, laisser les options par défaut.
Ensuite, sélectionner la dernière version disponible de l’archetype fournit par gwt-maven-plugin :
generation-02
Si rien ne s’affiche lorsque la valeur du filtre est « gwt », cliquer sur « Add archetype » et entrer les paramètres suivants :

Archetype Group Id : org.codehaus.mojo
Archetype Artifact Id : gwt-maven-plugin
Archetype Version : 2.5.1
archetype-05

Remplir le formulaire suivant comme dans cet exemple :
generation-03
Cliquer sur « Finish », et voilà le résultat :
generation-04

C’est plein de croix rouge, et c’est pour ça que j’écris cet article^^

haut

3. Description du contenu généré et nettoyage

Pour la suite, vérifier que l’on a bien la perspective JavaEE d’Eclipse.
Le contenu généré par l’archétype est structuré correctement, avec les 4 packages habituels d’un projet Maven :

  • src/main/java
  • src/main/resources
  • src/test/java
  • src/test/resources

On trouve également un package de plus : « target/generated-sources/gwt », j’expliquerai à quoi il sert et comment faire si vous ne le voyez pas chez vous dans un petit instant.
Tout d’abord, déplions le sous-dossier src/main/java : on retrouve bien nos 3 packages client, server et shared communs à tous les projets GWT.
On déplie ces 3 packages :
generation-06
C’est là que se trouvent nos erreurs : certaines classes n’existent pas.
Il va falloir les générer : premier conflit entre nos trois plugins qui savent tous les trois le faire de façon différente !
GPE va permettre de les générer, mais il faudra alors supprimer les goals « i18n » et « generateAsync » du composant gwt-maven-plugin pour ne pas avoir de comportements parasites à la compilation. Sur une petite POC, ça peut passer, mais en pratique, je n’arrive plus à me passer de Maven…
gwt-maven-plugin permet également de générer les fichiers manquant en ligne de commande en tapant « mvn generate-source ». Remarquez que le goal « generate-source » est avant le goal « compile » dans le cylcle de vie Maven, ce qui assure que les classes dont on parle ici seront toujours bien mises à jour au moment de la compilation, même si Eclipse affiche une erreur. Il suffit donc de générer les sources en ligne de commande et de mettre à jour Eclipse (F5) pour faire disparaître les marqueurs.
m2e, enfin, permet de lancer la commande ci-dessus et de rafraîchir Eclipse via un menu contextuel : clic-droit sur le projet puis « Run As > Maven generate sources ».

Les fichiers générés sont placés dans un sous-dossier du projet. Par défaut : « target/generated-sources/gwt ».
Si ce dossier apparait dans votre « Java Resources », tant mieux : passez au chapitre suivant. Mais, pour avoir joué ce tutoriel avec plusieurs versions d’Eclipse et de ces plugins, il arrive parfois, que ce dossier n’ai pas été ajouté au Build Path.
Pour l’ajouter manuellement, on connait le bouton « Add folder… » de l’interface « Java Build Path » accessible depuis le menu contextuel du projet (clic-droit). Mais ce n’est pas une solution pérenne puisqu’une mise à jour du projet (« Maven > Update Project… ») fera disparaitre à nouveau ce dossier de notre projet Eclipse.
L’autre solution que je vous propose consiste donc à ajouter un plugin dans le fichier pom.xml, afin de toujours s’assurer que le dossier « target/generated-sources/gwt » est dans le BuildPath :
1) Ouvrir le fichier pom.xml et y ajouter le plugin ci-dessous :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/gwt/</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

2) Faire un clic-droit sur le projet puis sélectionner « Maven > Update project configuration… »
explication-06

A ce stade, les erreurs indiquées par Eclipse devraient avoir disparu.
Il peut toutefois rester des erreurs liées au plugin m2e et aux goals i18n et generateAsync :
explication-03
Pour l’instant, je ne vois pas d’autres solutions que de les ignorer. Elles devraient disparaitre dans les prochaines versions de ces plugins.
explication-04

haut

4. Lancement du projet dans un navigateur

On y va ! Faire un clic-droit sur votre projet puis « Run As… » > « Web application »
lancement-01

Et ça marche !
Non ?
J’ai rencontré le bug ci-dessous en utilisant SpringSource ToolSuite. Je pense qu’il est du à une incompatibilité entre GPE et certaines versions d’Eclipse :

Missing required argument 'module[s]'
Google Web Toolkit 2.5.0
DevMode [-noserver] [-port port-number | "auto"] [-whitelist whitelist-string] [-blacklist blacklist-string] [-logdir directory] [-logLevel level] [-gen dir] [-bindAddress host-name-or-address] [-codeServerPort port-number | "auto"] [-server servletContainerLauncher[:args]] [-startupUrl url] [-war dir] [-deploy dir] [-extra dir] [-workDir dir] module[s]

where
  -noserver        Prevents the embedded web server from running
  -port            Specifies the TCP port for the embedded web server (defaults to 8888)
  -whitelist       Allows the user to browse URLs that match the specified regexes (comma or space separated)
  -blacklist       Prevents the user browsing URLs that match the specified regexes (comma or space separated)
  -logdir          Logs to a file in the given directory, as well as graphically
  -logLevel        The level of logging detail: ERROR, WARN, INFO, TRACE, DEBUG, SPAM, or ALL
  -gen             Debugging: causes normally-transient generated types to be saved in the specified directory
  -bindAddress     Specifies the bind address for the code server and web server (defaults to 127.0.0.1)
  -codeServerPort  Specifies the TCP port for the code server (defaults to 9997)
  -server          Specify a different embedded web server to run (must implement ServletContainerLauncher)
  -startupUrl      Automatically launches the specified URL
  -war             The directory into which deployable output files will be written (defaults to 'war')
  -deploy          The directory into which deployable but not servable output files will be written (defaults to 'WEB-INF/deploy' under the -war directory/jar, and may be the same as the -extra directory/jar)
  -extra           The directory into which extra files, not intended for deployment, will be written
  -workDir         The compiler's working directory for internal use (must be writeable; defaults to a system temp dir)
and
  module[s]        Specifies the name(s) of the module(s) to host

La solution : utiliser une autre version d’Eclipse ou se passer de GPE :)

Merci de me signaler les autres problèmes rencontrés.

haut

5. Conclusion

Voilà un projet GWT qui marche et avec lequel on va pouvoir s’amuser. En pratique, ces plugins sont gourmands en ressources et ne sont utilisables que dans des cas très standards.
Pour aller lus loin, je vous recommande de commencer par lire cette doc.