I. Introduction▲
Le but de cet article est de présenter ce qu'offre le Framework GWT pour la création d'interfaces Web riches reposant sur la technologie AJAX et la consommation de services distants en utilisant la technologie asyncronous RPC.
Les bibliothèques et versions d'Eclipse utilisées pour les besoins de l'article :
- JDK Oracle 7 ;
- Eclipse JEE LUNA ;
- GWT 2.6 ;
- Google Plugin pour ECLIPSE 3.8.
II. Installation de l'environnement▲
II-A. Prérequis▲
Il faut en premier lieu disposer au minimum du JDK 7 ou 8, la version 9 n'étant à ce jour proposée par ORACLE qu'en « test release ».
Le deuxième prérequis est l'environnement de développement intégré Eclipse. Disponible pour tous les systèmes d'exploitation sur le site de téléchargement de la fondation Eclipse, il faut choisir la déclinaison JEE for web developpers. Cet article s'appuie sur la version Eclipse LUNA.
Dans la mesure où ce tutoriel s'adresse à un public connaissant déjà JAVA et un IDE, il ne détaillera pas l'installation de ces deux applicatifs de base pour faire du développement Web avec JEE.
II-B. Installation de GWT dans l'environnement de développement▲
Nous installerons GWT directement depuis Eclipse : menu Help -> Eclipse MarketPlace.
Depuis l'onglet Search de la boite de dialogue Eclipse Marketplace, on lancera une recherche avec le mot GWT pour faire apparaître le plugin GWT pour Eclipse.
Une fois le plugin choisi, il vous proposera les modules que vous pouvez installer. Je conseille de ne pas prendre le module relatif à Android qui ne nous intéresse pas dans le cadre de cet article.
Veuillez ignorer également les alertes de sécurité qui nous informent que le plugin n'est pas signé.
II-C. Environnement de production▲
Le but de ce tutoriel est de créer et utiliser un service distant avec GWT RPC, ce que nous ferons avec l'environnement de développement déjà installé.
Pour déployer cette solution sur un environnement de production, il faut télécharger un serveur JEE simple (servlet et JSP) tel que TOMCAT qui s'administre facilement avec Eclipse. Mais ce processus de déploiement en production ne sera pas décrit dans cet article.
III. Le cahier des charges▲
On souhaite développer un écran Web, permettant d'entrer deux nombres, puis de choisir de les multiplier ou de les additionner. L'interface graphique utilisateur se présentera comme ci-dessous :
Le cahier des charges nous impose également d'avoir le traitement métier qui soit dissocié de l'interface graphique. On aura donc un objet métier que l'on désignera OperatorService, aussi éloigné que l'on souhaite et qui nous fournira deux méthodes : additionner et multiplier. Cette architecture nous fait immédiatement penser à la consommation d'un service Web en REST ou en SOAP. Néanmoins un grand nombre de tutoriels illustrent parfaitement cette technologie et dans le cadre de cet article, nous invoquerons ce service distant via GWT RPC.
IV. Développement de l'application▲
IV-A. Création du squelette de l'application▲
Le plugin GWT permet dans Eclipse de créer très facilement des applications GWT. En l'occurrence, la barre des boutons sous le menu s'est enrichie d'une icône Google qui fait apparaître un menu. Dans ce menu, on choisira le sous-élément New Web Application Project…
Une boite de dialogue nouveau projet apparaît. Il faut y préciser le nom du projet et le nom du package qui contiendra le code source développé. Les autres champs peuvent garder leur valeur par défaut. Il faut également décocher l'option Generate project sample code pour créer un projet vierge.
Le squelette de notre application Calculatrice est maintenant créé.
Nous allons créer deux sous-packages : com.calcul.client et com.calcul.server.
Le package x.y.client contiendra l'interface graphique utilisateur et le stub du service distant.
Le package server contiendra la Servlet distante qui implémentera le service.
On obtient dans l'explorateur de projet le squelette suivant.
La classe principale dite de départ de l'application s'appellera Calculatrice. On doit indiquer dans le fichier Calculatrice.gwt.xml que la classe Calculatrice est le point d'entrée de l'application.
Voici d'ailleurs le fichier Calculatrice.gwt.xml à ajouter dans le package com.calcul :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.6.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.6.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='calculatrice'>
<!-- appliquer le web toolkit principal -->
<inherits name='com.google.gwt.user.User'/>
<!-- appliquer le style d'IHM GWT par defaut. vous pouvez -->
<!-- changer le theme de votre application GWT en decommentant -->
<!-- une des lignes ci-dessous -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Specifier le point d'entree -->
<entry-point class='com.calcul.client.Calculatrice'/>
<!-- activer le SuperDevMod -->
<add-linker name="xsiframe"/>
</module>
À la lecture de ce fichier, on comprend qu'une application GWT se décompose en modules et que notre application est constituée d'un seul module.
Il y a un tag réservé au Super Dev Mode. Cette fonctionnalité permettra de tester l'application dans un navigateur sans avoir recours à un serveur avec des temps de réponse très satisfaisants.
Comme pour toute application JEE, nous devons aussi disposer d'un fichier Calculatrice.html dans le répertoire WAR :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="Calculatrice.css">
<title>Calculator Web Application Project</title>
<!-- ce script charge le module compile -->
<script type="text/javascript" language="javascript" src="calculatrice/calculatrice.nocache.js"></script>
</head>
<body>
<!-- OPTIONAL: inclure pour avoir le support de l'historique -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<!-- instruction pour les navigateurs ne supportant pas JavaScript -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
votre navigateur doit accepter JavaScript pour que l'application fonctionne correctement
</div>
</noscript>
<h1>Calculator Web Application Project</h1>
</body>
</html>
Le code Java de notre application sera compilé en JavaScript. Cette page HTML doit donc indiquer que c'est ce code JavaScript qu'il faut exécuter : <script type="text/javascript" language="javascript" src="calculatrice/calculatrice.nocache.js"></script>
Bien entendu, on utilisera un fichier Calculatrice.css pour modifier l'apparence dans l'IHM des boutons Additionner et Multiplier.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 40px 0px 70px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
font-family: Arial;
color: #ffffff;
font-size: 14px;
background: #3498db;
padding: 6px 16px 6px 16px;
text-decoration: none;
}
.btn:hover {
background: #3cb0fd;
background-image: -webkit-linear-gradient(top, #3cb0fd, #3498db);
background-image: -moz-linear-gradient(top, #3cb0fd, #3498db);
background-image: -ms-linear-gradient(top, #3cb0fd, #3498db);
background-image: -o-linear-gradient(top, #3cb0fd, #3498db);
background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
text-decoration: none;
}
À ce stade, nous n'avons pas écrit une ligne de Java, mais nous avons le squelette propre de notre application créée ex nihilo comme ci-dessous :
IV-B. Création de la classe principale▲
Nous avons précédemment défini dans le fichier Calculatrice.gwt.xml que le point d'entrée de l'application était la classe Calculatrice.
Voyons comment on crée cette classe dans le package client :
En GWT, il n'y a pas de classe principale, mais un EntryPoint que la classe Calculatrice doit implémenter.
L'unique méthode de l'interface EntryPoint à implémenter est onModuleLoad() qui place l'objet Ecran en affichage principal
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
package com.calcul.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
public class Calculatrice implements EntryPoint
{
@Override
public void onModuleLoad()
{
Ecran main = new Ecran();
RootPanel.get().add(main);
}
}
IV-C. Développement de l'interface graphique▲
Il faut créer avec Eclipse une classe Ecran qui hérite de la classe Composite dans le package client
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
package com.calcul.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
public class Ecran extends Composite {
private VerticalPanel vPanel = new VerticalPanel();
private HorizontalPanel hPanel1, hPanel2, hPanel3, hPanel4;
private Label op1Lbl, op2Lbl, resultLbl;
private TextBox op1Txt, op2Txt, resultTxt;
private Button addBtn, multBtn;
public Ecran() {
this.initWidget(this.vPanel);
this.op1Lbl = new Label("Operande 1 : ");
this.op1Txt = new TextBox();
this.hPanel1 = new HorizontalPanel();
this.hPanel1.add(op1Lbl);
this.hPanel1.add(op1Txt);
this.hPanel1.setSpacing(5);
this.vPanel.add(hPanel1);
this.op2Lbl = new Label("Operande 2 : ");
this.op2Txt = new TextBox();
this.hPanel2 = new HorizontalPanel();
this.hPanel2.add(op2Lbl);
this.hPanel2.add(op2Txt);
this.hPanel2.setSpacing(5);
this.vPanel.add(hPanel2);
this.addBtn = new Button("Additionner");
this.addBtn.setStyleName("btn");
this.addBtn.addClickHandler(new AddBtnHandler());
this.multBtn = new Button("Multiplier");
this.multBtn.setStyleName("btn");
this.multBtn.addClickHandler(new MultBtnHandler());
this.hPanel3 = new HorizontalPanel();
this.hPanel3.add(addBtn);
this.hPanel3.add(multBtn);
this.hPanel3.setSpacing(20);
this.vPanel.add(hPanel3);
this.resultLbl = new Label("Resultat : ");
this.resultTxt = new TextBox();
this.hPanel4 = new HorizontalPanel();
this.hPanel4.add(resultLbl);
this.hPanel4.add(resultTxt);
this.hPanel4.setSpacing(5);
this.vPanel.add(hPanel4);
}
private class AddBtnHandler implements ClickHandler {
@Override
public void onClick(final ClickEvent event) {
// add your code here
}
}
private class MultBtnHandler implements ClickHandler {
@Override
public void onClick(final ClickEvent event) {
// add your code here
}
}
}
Nous venons de créer l'interface graphique utilisateur demandée, mais sans effet par un clic sur les deux boutons.
Il nous faut maintenant créer et consommer le service distant via RPC.
IV-D. Développement du service RPC▲
Il faut dans un premier temps créer dans le package client deux interfaces : OperatorService et OperatorServiceAsync
2.
3.
4.
5.
6.
7.
8.
9.
package com.calcul.client;
import com.google.gwt.user.client.rpc.*;
@RemoteServiceRelativePath("operator")
public interface OperatorService extends RemoteService {
String additionner(String input1, String input2);
String multiplier(String input1, String input2);
}
Cette interface qui hérite de RemoteService indique qu'un objet distant qui implémentera OperatorService exposera deux méthodes additionner et multiplier.
2.
3.
4.
5.
6.
7.
8.
9.
10.
package com.calcul.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface OperatorServiceAsync {
void additionner(String input1, String input2, AsyncCallback<String> callback )
throws IllegalArgumentException;
void multiplier(String input1, String input2, AsyncCallback<String> callback )
throws IllegalArgumentException;
}
Sachant que ce code sera transformé en JavaScript la compréhension de cette interface asynchrone vient plus facilement en se remémorant le fonctionnement de l'objet AJAX XmlHttpResponse qui ouvre une connexion, envoie des paramètres et en reçoit en retour au format texte ou XML.
Et enfin dans le package server, on doit implémenter l'interface OperatorService dans une RemoteServiceServlet.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
package com.calcul.server;
import com.calcul.client.OperatorService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
@SuppressWarnings("serial")
public class OperatorServiceImpl extends RemoteServiceServlet implements
OperatorService
{
@Override
public String additionner(String input1, String input2)
{
float val1 = Float.valueOf(input1).floatValue();
float val2 = Float.valueOf(input2).floatValue();
float res = val1 + val2;
return String.valueOf(res);
}
@Override
public String multiplier(String input1, String input2)
{
float val1 = Float.valueOf(input1).floatValue();
float val2 = Float.valueOf(input2).floatValue();
float res = val1 * val2;
return String.valueOf(res);
}
}
Bien entendu comme dans toute application JEE, il faut indiquer dans le fichier web.xml où trouver cette servlet et comment la nommer.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee">
<!-- Servlets -->
<!-- Default page to serve -->
<servlet>
<servlet-name>operatorServlet</servlet-name>
<servlet-class>com.calcul.server.OperatorServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>operatorServlet</servlet-name>
<url-pattern>/calculatrice/operator</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Calculatrice.html</welcome-file>
</welcome-file-list>
</web-app>
IV-E. Consommer le service▲
On peut maintenant appeler le service dans la classe Ecran en surchargeant la méthode onClick des deux ClickHandler de la manière suivante.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
private class AddBtnHandler implements ClickHandler
{
@Override
public void onClick(final ClickEvent event)
{
final OperatorServiceAsync getService = GWT.create(OperatorService.class);
getService.additionner(op1Txt.getText(), op2Txt.getText(), new AsyncCallback<String>()
{
public void onFailure(Throwable caught)
{
System.out.println(event.getSource().toString());
}
public void onSuccess(String result)
{
resultTxt.setText(result);
}
});
}
}
private class MultBtnHandler implements ClickHandler
{
@Override
public void onClick(final ClickEvent event)
{
final OperatorServiceAsync getService = GWT.create(OperatorService.class);
getService.multiplier(op1Txt.getText(), op2Txt.getText(), new AsyncCallback<String>()
{
public void onFailure(Throwable caught)
{
System.out.println(event.getSource().toString());
}
public void onSuccess(String result)
{
resultTxt.setText(result);
}
});
}
}
V. Test de l'application avec Super Dev Mode▲
Le Super Dev Mode permet de tester notre application dans un bac à sable réduit à un simple navigateur.
Pour cela, il suffit de choisir par un clic droit dans l'explorateur de projet Run as … Web Application (Super Dev Mode).
Après quelques secondes, la vue développement mode permet de lancer le test dans le navigateur souhaité.
Le mode Super Dev Mode permet de tester à chaud chaque modification du code source après sauvegarde des fichiers source dans Eclipse en cliquant dans le navigateur sur l'icône GWT en bas à droite qui relance la compilation dans le navigateur.

VI. Conclusion et remerciements▲
GWT est un Framework professionnel. À ce titre, il a vocation à être utilisé dans l'environnement habituel de développement JEE et tout particulièrement à l'aide d'un outil de Build tel que MAVEN et de tests unitaires comme JUnit.
Le projet MOJO propose un plugin gwt-maven (pour construire un projet GWT dans Eclipse comme on le ferait avec n'importe quel projet JEE. Les sources et informations sur ce plugin sont disponibles sur le site du projet MOJO à l'URL : http://mojo.codehaus.org/gwt-maven-plugin/.
Quant à JUnit, il est implémenté dans GWT pour tester la plupart des composants que le Framework crée en JavaScript. La documentation est également disponible sur le site du projet GWT à l'URL : http://www.gwtproject.org/doc/latest/tutorial/JUnit.html.
Cet article nous a permis, à travers un exemple simple de comprendre :
- comment GWT permet de réaliser une interface AJAX en écrivant uniquement Java ;
- comment créer un service distant et comment l'invoquer en GWT RPC.
On a également pu constater à quel point Eclipse intègre GWT pour le développement et le test.
Nous tenons à remercier Claude Leloup pour sa relecture attentive de cet article et Mickaël Baron pour la mise au gabarit.




















