Developpez.com

Plus de 14 000 cours et tutoriels en informatique professionnelle à consulter, à télécharger ou à visionner en vidéo.

Tutoriel sur le développement d'applications Web avec GWT 2.6 et Eclipse Luna

Ce tutoriel présente le développement d'applications Web avec GWT version 2.6 et l'environnement de développement Eclipse Luna.

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum 6 commentaires Donner une note à l'article (5) .

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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.

Image non disponible

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.

Image non disponible

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.

Image non disponible

Veuillez ignorer également les alertes de sécurité qui nous informent que le plugin n'est pas signé.

Image non disponible

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 :

Image non disponible

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.

Image non disponible

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.

Image non disponible
Image non disponible

On obtient dans l'explorateur de projet le squelette suivant.

Image non disponible

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 :

 
Sélectionnez
1.
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 :

 
Sélectionnez
1.
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.

 
Sélectionnez
1.
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 :

Image non disponible

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 :

Image non disponible

En GWT, il n'y a pas de classe principale, mais un EntryPoint que la classe Calculatrice doit implémenter.

Image non disponible

L'unique méthode de l'interface EntryPoint à implémenter est onModuleLoad() qui place l'objet Ecran en affichage principal

Calculatrice.java
Sélectionnez
1.
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

Ecran
Sélectionnez
1.
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

OperatorService
Sélectionnez
1.
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.

OperatorServiceAsync
Sélectionnez
1.
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.

OperatorServiceImpl
Sélectionnez
1.
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.

web.xml
Sélectionnez
1.
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.

AddBtnHandler
Sélectionnez
1.
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).

Image non disponible

Après quelques secondes, la vue développement mode permet de lancer le test dans le navigateur souhaité.

Image non disponible

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.

Image non disponible
Image non disponible

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.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2015 Marc Autran. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.