219
GWT Créer des applications web interactives avec Google Web Toolkit (versions 1.7 et 2.0) Directeur technique de Sfeir Benelux (groupe Sfeir) Olivier Gérardin Préface de Didier Girard Directeur des opérations et de l'innovation de Sfeir Paris (groupe Sfeir)

GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

GWTCréer des applications web interactives

avec Google Web Toolkit

(versions 1.7 et 2.0)

Directeur technique de Sfeir Benelux (groupe Sfeir)

Olivier Gérardin

Préface deDidier Girard

Directeur des opérations et de l'innovation de Sfeir Paris (groupe Sfeir)

Page 2: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

978-2-10-054628-2

Page 3: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Préface

JavaScript : je t’aime, moi non plus

Depuis que je développe des sites ou des applications web, j’ai toujours recherchéla technologie qui me permettrait de développer des sites web avec la meilleureexpérience utilisateur. La raison est simple, meilleure est l’expérience utilisateur etplus il y a de chances pour que l’internaute revienne. C’est tellement simple, c’esttellement vrai. Cette quête permanente de la meilleure technologie fait certainementde moi un technophile.

Je n’en suis pas moins un technophobe : la technologie ne m’intéresse pas pour cequ’elle est, mais pour ce qu’elle me permet de créer. Ainsi, chaque mois je teste ungrand nombre de « nouveautés qui vont révolutionner le monde du développementlogiciel » et j’en rejette autant avec tout le dégoût provoqué par la perte du tempsconsacré. Pour tester une technologie, mon approche est simple, quinze minutes pourcomprendre, une heure pour faire un Hello World et huit heures pour résoudre unproblème qui me tient à cœur. C’est ainsi qu’au fil des années, j’ai développé des sitesweb en Shell, Perl, SSJS, ASP, .NET, Flex et Java. Année après année, une technologierevenait sur mon banc de test : sa puissance, son universalité, sa simplicité me plaisait.Pourtant, après quelques heures d’utilisation, je n’avais qu’une envie : la jeter par lafenêtre. Cette technologie était JavaScript.

Pendant des années mes sites ont donc contenu le minimum syndical de JavaScriptet je voyais arriver la vague AJAX comme un raz de marée qui allait m’engloutir fautede pouvoir aimer le cœur de cette approche.

GWT : Bon pour l’utilisateur, bon pour le développeur

GWT va me sauver. Sur le papier, cette technologie pensée par Google correspondà ce que j’attendais : bonne pour l’utilisateur, bonne pour le développeur. En cinqminutes, j’ai compris son fonctionnement et sa puissance « coder en java, compileren JavaScript » ; en quinze minutes, j’ai fait mon premier Hello World ; en huit heuresj’ai développé une application qui me semblait impossible à réaliser quelques heuresauparavant. J’étais conquis. L’accueil par les développeurs Web 2.0 était pourtantmitigé, l’approche adoptée par GWT blessait les puristes ou les influenceurs du Web :JavaScript n’était plus considéré comme un langage pour programmer le Web, mais

Page 4: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

VI GWT

comme un simple assembleur permettant d’exécuter le Web. L’intensité du rejet parces puristes était sans doute à l’échelle du potentiel de GWT qui :

• propose une bonne expérience utilisateur ;• est facile d’utilisation ;• est compatible avec les meilleurs environnements de développement ;• aide à résoudre des problèmes difficiles de manière simple et efficace ;• est soutenu par une communauté enthousiaste et en expansion rapide ;• facilite la maintenance ;• garantit une bonne performance ;• est fun ;• est gratuit et libre d’utilisation.

Et nous : Invention et Innovation

En créant GWT, Google ouvre une nouvelle ère du développement et rend accessibleà tous les développeurs la réalisation de sites web de nouvelle génération. Cetteinvention permet d’améliorer la satisfaction client tout en innovant, c’est pour celaque je l’ai adoptée et que je la conseille à mes clients.

Ce livre

Il existait actuellement beaucoup d’ouvrages en anglais sur GWT, il manquait unouvrage en français qui permette aux nombreux développeurs francophones dedécouvrir cette technologie et ces concepts dans leur langue. C’est ce que proposeOlivier avec talent. Présenter une technologie n’est jamais aisée, les livres sont souventtrop techniques ou pas assez, c’est selon. Ce livre a le bon dosage, il vous permettraà la fois de bien débuter avec la technologie mais aussi d’approfondir les conceptsimportants afin de développer des applications ayant la qualité requise pour uneutilisation en entreprise. Je le conseille donc à toute personne qui veut bien démarreravec GWT, que ce soit dans le cadre d’une activité de veille technologique, dans lecadre du démarrage d’un projet ou dans le cadre de monitorat.

Bonne aventure technologique,

Didier Girardhttp://www.google.com/search?q=Didier+Girard

Page 5: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Table des matières

Préface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . V

Avant-propos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XIII

Première partie – Développer avec GWT

Chapitre 1 – De HTML à GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1 Au commencement était HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.1.1 La notion d’URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.1.2 La technologie derrière les pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.2 L’apparition des pages dynamiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.2.1 CGI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.2.2 Server-side Scripting : PHP & Cie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.2.3 Java côté client : les applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.2.4 Les servlets et JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2.5 Client-side Scripting et JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2.6 Du vrai client-serveur en JavaScript : XmlHttpRequest et AJAX . . . . . . . . . . . . 9

1.3 L’étape suivante : Google Web Toolkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.3.1 Les challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.3.2 Les réponses de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.3.3 L’historique de la plate-forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Page 6: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

VIII GWT

Chapitre 2 – Hello, GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.1 L’environnement de développement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.1.1 Les plugins GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2.1 Le choix de la plate-forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2.2 Installation d’Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.2.3 Installation de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.2.4 Google Plugin pour Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.3 Anatomie d’un projet GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.3.1 Nommage des packages et structure des dossiers . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.3.2 La page HTML hôte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.3.3 Le point d’entrée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3.4 Le fichier module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.4 Hello, GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4.1 Création du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4.2 Création du module GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.4.3 Création du point d’entrée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.4.4 Création de la page HTML hôte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

2.4.5 Lancement de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

Chapitre 3 – Développer avec GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.1 Hosted mode vs web mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.2 Contraintes sur le code Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.2.1 Support du langage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.2.2 Émulation des classes du JRE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.3 Lancer en mode hôte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

3.3.1 Le serveur d’applications intégré . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.4 Compiler et lancer en mode web. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.4.1 Les fichiers générés par le compilateur GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3.5 Développement avec l’IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

3.5.1 Debug et cycle de développement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Page 7: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Table des matières IX

Chapitre 4 – Widgets, panels, etc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.1 Une interface graphique dynamique. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

4.1.1 Les widgets GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.1.2 GWT et les aspects graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

4.2 Widgets et panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.2.1 Événements et Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

4.2.2 Widgets simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

4.2.3 Panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

Chapitre 5 – Communiquer avec le serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.1 Code client vs code serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.2 Les principes de GWT RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

5.2.1 Classes et interfaces mises en jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

5.3 La création d’un service pas à pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

5.3.1 Écriture des interfaces et de l’implémentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

5.3.2 Déploiement sur le serveur embarqué . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

5.3.3 La réalisation d’un appel RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.4 Exemple complet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

5.5 Utilisation d’un serveur externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

5.6 Contraintes de sérialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

5.6.1 Types sérialisables déclarés par l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

5.7 Les exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

Deuxième partie – Aller plus loin avec GWT

Chapitre 6 – Internationalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

6.1 Les possibilités d’internationalisation de GWT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

6.1.1 Importer le module I18N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

6.2 Internationalisation « statique » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

6.2.1 L’interface Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

6.2.2 Gestion des locales multiples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

6.2.3 Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

6.2.4 L’interface ConstantsWithLookup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

Page 8: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

X GWT

6.2.5 L’interface Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

6.3 Le formatage des dates et nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

6.3.1 NumberFormat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

6.3.2 DateTimeFormat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

Chapitre 7 – Mécanismes avancés du compilateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

7.1 JSNI (JavaScript Native Interface) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

7.1.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

7.1.2 Écrire une méthode JSNI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

7.1.3 Accéder à des objets Java depuis JSNI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

7.1.4 Règles de passage de paramètres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

7.1.5 Traitement des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

7.2 Deferred Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

7.2.1 Principes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

7.2.2 Mise en oeuvre du Deferred Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Chapitre 8 – Le mécanisme d’historique de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

8.1 Le problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

8.2 L’approche de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

8.2.1 URL et fragment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

8.2.2 Encoder l’état de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

8.2.3 Mise en oeuvre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

8.3 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

8.3.1 Créer une entrée dans l’historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

8.3.2 Réagir à un événement historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

8.4 Le widget Hyperlink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Chapitre 9 – Envoyer des requêtes HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

9.1 Au-delà de GWT RPC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

9.2 Requêtes HTTP en GWT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

9.2.1 Réalisation d’un appel HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

9.3 Manipulation de XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

9.3.1 Le DOM XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

9.3.2 Parsing d’un document XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Page 9: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Table des matières XI

9.3.3 Création d’un document XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

9.4 Manipulation de JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

9.5 Accès à des web services JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

9.6 Proxy serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

Chapitre 10 – Créer ses propres widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

10.1 Sous-classer un widget existant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

10.2 Utiliser la classe Composite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

10.3 Implémenter complètement un widget en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

10.4 Implémenter tout ou partie d’un widget en JavaScript. . . . . . . . . . . . . . . . . . . . . . . 136

Chapitre 11 – Bibliothèques tierces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

11.1 Bibliothèques de composants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

11.1.1 GWT-ext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

11.1.2 Ext-GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

11.1.3 SmartGWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

11.1.4 Autres composants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

11.2 Bibliothèques utilitaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

11.2.1 Gwittir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

11.2.2 GWT Server Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

11.2.3 Google API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

Chapitre 12 – GWT 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

12.1 Obtenir la dernière version de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

12.1.1 Prérequis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

12.1.2 Génération de GWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

12.2 OOPHM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

12.2.1 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

12.3 Code splitting & SOYC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

12.3.1 Insérer un split point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

12.3.2 Story Of Your Compile (SOYC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

12.3.3 Optimiser avec le code splitting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Page 10: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

XII GWT

12.4 UiBinder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

12.4.1 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

12.4.2 Un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

12.5 ClientBundle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Annexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

Liste des classes de la bibliothèque d’émulation JRE (chapitre 3) . . . . . . . . . . . . . . . . . . . . . 181

Exemple de FlexTable avec cellule baladeuse (chapitre 4) . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Exemple d’appel à un service RPC (chapitre 5) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

Exemple de mise en œuvre du mécanisme d’historique (chapitre 8) . . . . . . . . . . . . . . . . . . 188

Appel à un service web JSON (chapitre 9) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191

Exemple d’utilisation de l’API Google Gears (chapitre 11) . . . . . . . . . . . . . . . . . . . . . . . . . 194

Exemple d’utilisation d’UiBinder pour créer un widget composite (chapitre 12) . . . . . . . . 197

Webographie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Page 11: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Avant­propos

Le Google Web Toolkit, ou GWT, est apparu en 2006 un peu comme un OVNIsur la scène du développement d’applications dites RIA (Rich Internet Applications) ou« Web 2.0 ». En effet, il ne rentrait dans aucune des catégories d’outils existant alorspour faciliter le développement de ce genre d’applications. Était-ce un frameworkweb de plus ? Non... Une énième bibliothèque de composants JavaScript ? Non...Une nouvelle plate-forme nécessitant encore un plugin pour fonctionner dans lenavigateur ? Non plus...

GWT est fondé sur un concept tellement original qu’il n’a pas convaincu grandmonde à l’époque : développer et mettre au point en pur Java, et traduire en JavaScriptau moment de déployer l’application sur le Web. Les avantages : on développe dansun langage familier et avec un typage fort (Java), dans un environnement familier(son IDE préféré – Eclipse, NetBeans, peu importe), avec des concepts familiers(boutons, panels, listeners, MVC, etc.) ; par conséquent la courbe d’apprentissage pourdes développeurs Java est très rapide. D’autre part, toute la complexité de l’adaptationaux différents navigateurs est entièrement assumée par le traducteur Java-JavaScript,et le cauchemar de la prise en compte des différentes variantes de JavaScript entreFirefox, IE, Safari, n’est plus qu’un souvenir.

GWT est la traduction technique de la vision qu’a Google des technologies duWeb 2.0 : « The browser is the platform » (le navigateur est la plate-forme). GWTn’impose pas de nouveau runtime (pas de plugin nécessaire), il profite de l’infrastructureet des outils en place, et s’intègre parfaitement dans les architectures et avec lestechnologies existantes. Il offre une transition idéale entre le développement classiqueet le développement d’applications RIA, avec un investissement humain et techniqueminimal.

La promesse semble trop belle pour être vraie, et pourtant... difficile de lui trouverdes défauts : si les premières versions souffraient de quelques problèmes, GWT n’acessé de progresser, et depuis la version 1.4, on peut considérer qu’il est totalementfiable et efficace, et l’a prouvé sur de nombreux projets. La licence initiale, jugéerestrictive par certains, a été remplacée par la licence Apache 2.0, considérée commeune des plus libérales de l’Open Source, ce qui garantit la pérennité du produit. Le

Page 12: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

XIV GWT

groupe de discussion consacré à GWT compte plus de 20 000 membres, preuve de lavitalité de la plate-forme.

J’ai personnellement découvert GWT en 2006, et l’approche m’a immédiatementséduite car elle me permettait enfin de réconcilier la création d’applications AJAXavec l’univers Java qui est le mien depuis de nombreuses années. Cela signifiait surtoutqu’il serait désormais possible de mener à bien un projet de ce type en se passant(enfin) d’un « expert JavaScript », ce magicien qui connaît par cœur les subtilités(et les bugs) des différentes implémentations dans les navigateurs, et les astuces quipermettent de les contourner...

Si l’approche de GWT m’a séduite, j’avoue avoir eu des doutes sur son applicabi-lité : comment émuler fidèlement la bibliothèque Java du Java Runtime Environment(JRE) ? Comment gérer la généricité ? Comment tester le code ? Les différencesentre le langage interprété qu’est JavaScript et le langage compilé qu’est Java neseront-elles pas rédhibitoires ? Et qu’en sera-t-il des performances ? Cependant, commeà son habitude, Google a fait taire mes doutes en apportant des réponses techniquesadéquates, efficaces et innovantes, et c’est sans doute ce qui a fait de GWT un produitréellement utilisable, et pas seulement un concept original.

À ce jour, cela fait deux ans que je participe à des projets mettant en œuvreGWT, et sur chacun d’eux il a fait la preuve de sa maturité de la meilleure manière :en se faisant oublier... une fois la configuration en place, il devient un rouage de lamécanique, et permet de se concentrer sur les problématiques propres à l’application.

L’intérêt des développeurs pour GWT est fort, mais malheureusement la littératurefrancophone sur le sujet est rare. J’espère donc au travers de ce livre vous donnertoutes les clés qui vous permettront de vous mettre à GWT.

À qui s’adresse ce livre ?

Ce livre s’adresse principalement aux développeurs Java ayant un minimum d’ex-périence et qui veulent découvrir et mettre en œuvre Google Web Toolkit. Uneconnaissance de base du langage Java est requise, ainsi que des principales technologiesdu Web : HTTP, HTML et CSS, JavaScript.

Pour les aspects client-serveur, une connaissance des principes de JEE (Java Enter-prise Edition) est souhaitable, même si nous essayerons d’en rappeler les principalesnotions lorsque nous y aurons affaire.

Page 13: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Avant­propos XV

Comment est structuré ce livre ?

Ce livre est découpé en deux parties :

• La première partie expose les bases qui permettent de comprendre GWT et deréaliser une application complète :

– en situant GWT dans son contexte et en expliquant ses ambitions et lecheminement qui a conduit à son apparition (chap. 1) ;

– en montrant comment mettre en place l’environnement logiciel nécessaireet créer un premier projet GWT (chap. 2). Vous y apprendrez également lafaçon de développer et déboguer avec GWT (chap. 3) ;

– en présentant les éléments de construction d’une application GWT, aussibien graphiques (widgets, chap. 4) qu’architecturaux (communication avecle serveur, chap. 5).

• La deuxième partie explorera des concepts avancés qui ne sont pas forcémentnécessaires dans toutes les applications GWT, mais qui peuvent répondre à uneproblématique spécifique :

– les possibilités d’internationalisation de GWT (chap. 6) ;– les possibilités avancées du compilateur : JSNI pour incorporer du code

JavaScript dans des méthodes Java, et le deferred binding pour générer desversions de code optimisées pour chaque environnement (chap. 7) ;

– la gestion de l’historique du navigateur (chap. 8) ;– les possibilités d’envoi direct de requêtes HTTP (chap. 9). On y verra aussi

comment manipuler XML et JSON avec GWT ;– les différentes manières de créer ses propres composants graphiques (chap.

10) ;– l’utilisation de bibliothèques tierces avec GWT, que ce soit pour enrichir

la palette de composants d’interface utilisateur ou pour fournir d’autresfonctionnalités (chap. 11) ;

– enfin, le chapitre 12 qui fera un tour d’horizon des nouveautés de GWT 2.0.

Si la première partie est plutôt linéaire, la seconde peut être consultée indépen-damment et servir de référence.

Remerciements

Ce livre n’aurait pas été possible sans la patience de mon épouse, qui a supporté lesnombreuses heures durant lesquelles j’étais plongé dans la rédaction de cet ouvrage.

Merci également à Didier Girard pour avoir eu l’amabilité de rédiger la préface,pour m’avoir mis en contact avec l’éditeur et pour ses conseils toujours précieux.

Page 14: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 15: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

PREMIÈRE PARTIE

Développer avec GWT

Page 16: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 17: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

De HTML à GWT

1

ObjectifDans ce chapitre, nous verrons comment le Web « original » a été conçu, quellestechnologies sont apparues pour le rendre plus dynamique et permettre l’émergenced’applications web. Nous verrons quels inconvénients ces technologies possèdent,et comment GWT propose une solution élégante à la création d’applications webdynamiques.

1.1 AU COMMENCEMENT ÉTAIT HTML

Le Web est un concept tellement familier que nous le manipulons quotidiennementpour la plupart d’entre nous. Mais le Web d’aujourd’hui est passablement différent duWeb tel qu’il a été imaginé par ses concepteurs, et tel qu’il a vu le jour.

Le Web, ou World Wide Web comme on l’appelait encore il n’y a pas si longtemps,est un concept inséparable de celui d’hypertexte. Pour schématiser, l’hypertexte, c’estdu contenu (au sens large : texte, images, médias), augmenté de liens qui permettentde passer d’une ancre (l’origine du lien) à la cible du lien (un autre document).

L’hypertexte a été implémenté de plusieurs manières, indépendamment du WWW,notamment dans des systèmes propriétaires et fermés. Tous les documents liés setrouvaient alors dans une base unique, permettant de créer des systèmes documentairesplus riches qu’une collection de simples documents, mais limités à leur propre domaine.La véritable révolution est née de la combinaison d’un langage de description de page(HTML pour Hypertext Markup Language), d’un protocole de transfert approprié auxcontenus hypertextes (HTTP pour Hypertext Transfer Protocol), et d’un réseau dedonnées à l’échelle mondiale, l’Internet. Il devenait alors possible de créer des pages

Page 18: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4 Chapitre 1. De HTML à GWT

avec un contenu « riche » (texte et images), incluant des liens vers n’importe quelleautre page, du même site ou d’un autre site quelque part sur la planète.

L’invention du Web

L’histoire retiendra que le Web a été conceptualisé au début des années 1990 au CERNà Genève, par Tim Berners­Lee, un physicien anglais, et Robert Cailliau, un informaticienbelge. Dès 1990, s’appuyant sur les concepts hypertextes existants, ils envisagent deconstruire une « toile » reliant des nœuds constitués de pages hypertextes, accessiblesau travers de « browsers » sur un réseau. Le concept se concrétise en 1992 avecl’apparition des premiers sites web, et se popularise dès 1993 avec la disponibilitédu premier browser graphique, Mosaic, qui remplace avantageusement Lynx, sonprédécesseur, un browser uniquement textuel.Dès lors, le nombre de sites et de pages web ne cessera d’augmenter.http://news.netcraft.com/archives/web_server_survey.html

1.1.1 La notion d’URL

Un concept essentiel à la réussite du Web est la notion d’URL, Uniform ResourceLocator. Dans le WWW, une URL est une chaîne de caractères formalisée qui est lafaçon normalisée de désigner une ressource accessible via le Web (en général une pageHTML, mais ce n’est pas obligatoire).

Une URL est constituée de plusieurs parties, dont certaines sont optionnelles etd’autres non. Dans sa forme la plus commune, une URL se présente de la manièresuivante :

http://code.google.com:80/webtoolkit/overview.html

On reconnaît les parties suivantes :

• http est le schema qui désigne le protocole à utiliser. À noter que sa valeurconditionne aussi le format du reste de l’URL ; on se limitera ici à la descriptiondes URL de type « http » ;

• code.google.com est le hostname, c’est-à-dire la désignation de la machine quihéberge la ressource ;

• 80 est le port IP à utiliser pour la connexion ;• le reste de l’URL constitue le chemin d’accès à la ressource sur le serveur.

Additionnellement, on peut encore trouver à la suite du chemin :

• une query string commençant par un point d’interrogation ? et spécifiant lavaleur de certains paramètres de la ressource, par exemple des critères derecherche : http://www.google.com/search?q=gwt ;

• un indicateur de fragment, commençant par un symbole dièse #, qui désigneune sous-partie de la ressource. Dans les pages HTML, cet indicateur est utilisépour désigner un signet, c’est-à-dire un marqueur dans la page (début de sectionpar exemple).

Page 19: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

1.2 L’apparition des pages dynamiques 5

L’URL joue un rôle essentiel dans le WWW car :

• elle permet la création de liens hypertextes : la cible de tout lien est désignéepar son URL ;

• elle permet l’inclusion de ressources (par exemple des images dans une pageHTML) en les désignant par leur URL.

Contrairement à un système fermé où la cible d’un lien appartient forcément ausystème au même titre que la source, le WWW permet de désigner n’importe quelleressource, quel qu’en soit le propriétaire, au travers de cette chaîne de caractères qu’estl’URL.

1.1.2 La technologie derrière les pages

Grâce au WWW et à la notion d’URL, il est donc aisé de saisir une « adresse web »sous forme d’une URL dans un navigateur, et d’accéder à la page correspondante.

Que se passe-t-il exactement quand nous tapons une adresse dans un navigateurpour accéder à un site web ? L’URL est alors « déréférencée », c’est-à-dire interprétéeet utilisée pour obtenir son contenu.

La séquence des événements est la suivante :

1. L’URL est parsée et ses composants isolés.

2. Si le hostname est indiqué par son nom, une requête DNS est faite pour obtenirl’adresse IP correspondante.

3. Une connexion TCP est établie vers cette machine, sur le port spécifié (ou unport par défaut qui dépend du protocole, 80 pour HTTP).

4. Une requête HTTP est construite et envoyée au serveur via la connexionouverte. Cette requête peut contenir un certain nombre d’informations, maiselle contient en particulier le chemin relatif du document accédé (dans notreexemple, /webtoolkit/overview.html).

5. Le serveur répond en renvoyant une réponse HTTP. Si tout est correct, laréponse contient le document demandé, ainsi que d’autres informations, enparticulier un type MIME qui indique le type du document.

6. En fonction du type MIME de la réponse, le navigateur interprétera lecontenu différemment : par exemple s’il s’agit de HTML, il va parser et afficherle document ; s’il s’agit d’un fichier PDF, il proposera de l’ouvrir ou de lesauvegarder, etc.

1.2 L’APPARITION DES PAGES DYNAMIQUES

Si ce système fonctionne de façon satisfaisante, il s’agit alors de pages statiques,c’est-à-dire de pages HTML stockées sous forme de fichiers, et servies telles quelles auclient. Le besoin apparaît de générer la réponse à une requête HTTP dynamiquement,par l’exécution de code côté serveur, plutôt que par le simple contenu d’un fichierHTML immuable.

Page 20: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6 Chapitre 1. De HTML à GWT

1.2.1 CGI

La norme CGI (Common Gateway Interface) résulte d’une idée simple : le résultatde l’appel à une URL est fourni par l’exécution d’une commande du systèmed’exploitation. La norme spécifie que les paramètres de la requête (la query string) sontpassés à la commande sous forme d’une variable d’environnement ; la sortie standardde la commande est capturée et constitue le résultat qui sera renvoyé au client.

C’est la configuration du serveur web qui détermine quelles sont les commandesqui sont ainsi exécutables ; en général un sous-répertoire nommé cgi-bin est désignéet toutes les URL qui pointent vers ce chemin sont considérées comme désignant unecommande CGI à exécuter plutôt que comme un fichier dont le contenu doit êtrerenvoyé.

Si CGI permet effectivement de générer des pages dynamiques et a été pendantdes années le fondement du Web dynamique, il souffre de plusieurs problèmes dontle principal est une inefficacité liée à son principe même : chaque requête déclenchel’exécution d’une commande au niveau de l’OS, et donc le lancement d’un processus.Or la création d’un processus est une opération assez coûteuse en termes de ressourceset de temps, et CGI s’est avéré peu adapté lorsqu’il s’agit de monter en charge.

1.2.2 Server­side Scripting : PHP & Cie

Dans le sillage de CGI, d’autres technologies pour rendre dynamique tout ou partie dela page HTML sont apparues, faisant appel à des mécanismes de scripting côté serveur.On retiendra celui qui a le mieux réussi : PHP.

PHP propose d’inclure à l’intérieur même de la page HTML des balises spécialesqui sont destinées à être décodées par le serveur. Entre ces balises, du code PHP, unlangage interprété et qui est devenu au fil des ans très riche en termes de bibliothèquesintégrées. Le serveur web, en général au travers d’un module dédié, reconnaît laprésence de code PHP dans une page et l’exécute. Le code PHP peut à son tourproduire du HTML dynamique qui sera inclus dans la page retournée au client.

Cette technologie a beaucoup d’avantages, notamment la versatilité et la relativesimplicité du langage PHP, et la possibilité pour un utilisateur de mettre en lignelui-même des pages PHP sans compromettre la sécurité. C’est ce qui a fait sonsuccès jusqu’à aujourd’hui. Cependant, PHP reste interprété et donc relativementpeu efficace.

1.2.3 Java côté client : les applets

Lorsque le langage Java a été introduit par Sun, sa première application a été lapossibilité d’insérer des mini-applications à l’intérieur même d’une page HTML : lesapplets. Ces mini-applications pouvaient disposer de toute la puissance et la richessede Java, fournir une interface graphique évoluée avec les composants AWT (et plustard Swing), ou bien dessiner directement en mode bitmap.

Page 21: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

1.2 L’apparition des pages dynamiques 7

Est-ce que l’interactivité, le dynamisme et la richesse des interfaces web seraientfinalement apportés par les applets Java ? Malheureusement, les applets ont rapidementet injustement été rangées dans la catégorie « gadgets animés qu’on peut mettre dansun coin d’une page web ». Les raisons de ce semi-échec sont multiples :

• le support de Java dans les navigateurs n’était pas universel à l’époque, et étaitsouvent associé à un temps de démarrage important ;

• l’implémentation de Java fournie par Microsoft présentait des différencesimportantes avec celle de Sun qui rendaient difficile la création d’une appletfonctionnant à la fois avec la JVM (Java Virtual Machine) de Sun et celle deMicrosoft ;

• l’interaction entre l’applet et le reste de la page est la plupart du tempsinexistante, car très complexe à mettre en place.

1.2.4 Les servlets et JSP

Pour répondre au problème de scalabilité des pages dynamiques, que CGI et PHPne résolvent pas de façon satisfaisante, Sun a imaginé le concept de servlet. Uneservlet est un composant logiciel (une classe Java) qui est écrit spécifiquement pourrépondre à une requête HTTP. La norme spécifie très précisément comment s’effectuel’invocation des servlets, la transmission des paramètres à la requête et en retour durésultat renvoyé par la servlet.

L’énorme avantage en comparaison de CGI est que chaque requête est traitéedans un fil d’exécution (thread), ce qui épargne le coût de la création systématiqued’un processus. Le serveur contrôle strictement le nombre de threads présents et ladistribution des requêtes aux threads au travers d’un dispatcher.

Les pages JSP (Java Server Pages) sont intimement reliées aux servlets — bienqu’elles se présentent sous une apparence semblable à une page PHP, c’est-à-diredu HTML dans lequel des balises spéciales introduisent des parties dynamiques —,puisqu’elles sont en fait compilées sous forme de servlet à leur première utilisation.On pourrait dire que servlets et JSP sont donc deux visages de la même technologie,ou plus exactement que JSP est une autre façon d’écrire des servlets.

Cependant, dans la mesure où les documents renvoyés par les servlets/pages JSPrestent des pages HTML complètes, l’interactivité n’est que peu améliorée en regarddes pages servies par CGI ou PHP, puisque la moindre action de l’utilisateur quinécessite une requête au serveur doit passer par une action de submit HTML et lerechargement complet de la page. Tout au plus a-t-on optimisé le temps de réponse duserveur.

1.2.5 Client­side Scripting et JavaScript

Pour franchir un pas dans l’interactivité, il fallait une technologie capable d’exécuterdu code côté client, pour pouvoir réagir aux événements qui se produisent dans lenavigateur (frappe d’une touche, changement du focus, clic sur un bouton, etc.). Ainsi

Page 22: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

8 Chapitre 1. De HTML à GWT

est apparue la balise HTML <script>, qui permet d’embarquer à l’intérieur d’unepage HTML du code exécutable sous forme de script, c’est-à-dire de code sourced’un langage interprété. En principe, les scripts inclus dans une page HTML peuventêtre écrits dans différents langages ; cependant, JavaScript est le seul langage dont lesupport natif soit commun à tous les navigateurs « grand public », et c’est à ce titrequ’il a connu un tel succès.

JavaScript a été créé par Netscape en 1995 et a connu différents noms (Mocha,LiveScript) avant que JavaScript soit adopté, comme résultat d’un accord avec Sunqui prévoyait que le navigateur dominant de l’époque embarque une JVM. JavaScripts’inspire de la syntaxe de Java, mais n’a pas de relation directe avec ce dernier.

Tableau 1.1 — Comparaison entre Java et JavaScript

Java JavaScript

Type de langage Orienté objet Orienté objet/fonctionnel

Typage Statique Dynamique

Mode d’exécution Semi­compilé (bytecode) +machine virtuelle

Interprété

Syntaxe Type « C »

Conventions denommage

Similaires

Pour interagir avec la page HTML qui le contient, un script JavaScript s’appuiesur le DOM (Document Object Model), qui est une abstraction sous forme d’arbre deséléments contenus dans la page HTML. L’arbre DOM initial est construit à partir deséléments HTML présents dans la page hôte ; la grande puissance du scripting web,c’est la possibilité de modifier dynamiquement le DOM, c’est-à-dire de changer lecontenu de la page HTML après son chargement. Au travers du DOM, un script peutà loisir ajouter des éléments dans la page, mais aussi retirer ou modifier des élémentsexistants ! La conjonction du scripting et du DOM offre les conditions pour créer desinterfaces sur une base HTML, mais capables de réagir en temps réel aux actions del’utilisateur, et de se modifier en conséquence.

Les premières applications concrètes ont été la validation de saisie côté client : eneffectuant des vérifications sur la longueur des champs, le format des données saisies,il était possible d’afficher un message à l’utilisateur et d’inhiber l’envoi de la requêteau serveur ; on évitait ainsi un aller-retour voué à l’échec. Le scripting a ensuite étéutilisé pour ajouter de la richesse aux interfaces, en particulier la création de menusdéroulants et l’implémentation de composants se rapprochant de plus en plus de leurséquivalents des clients lourds.

Cependant, il restait un obstacle à la réalisation d’interfaces fluides : toute requêteau serveur passait par un submit HTML et le rechargement complet de la page.

Page 23: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

1.3 L’étape suivante : Google Web Toolkit 9

1.2.6 Du vrai client­serveur en JavaScript : XmlHttpRequest et AJAX

En 2000, Microsoft introduit avec Exchange Server 2000 un client web nommé« Outlook Web Access » permettant d’accéder à toutes ses données (e-mail, calendrier,contacts, etc.) depuis un navigateur web. La nouveauté de ce client web, c’est qu’ilreproduit de façon quasi identique le client lourd Outlook, et surtout met à jour lesdonnées affichées sans jamais recharger la page courante en entier. Pour y parvenir,le client JavaScript utilise la nouvelle classe XmlHttpRequest qui permet d’envoyerdirectement une requête au serveur, sans passer par un submit. La réponse à la requêteest traitée de façon asynchrone, c’est-à-dire que le flux d’exécution continue jusqu’àce que la réponse soit disponible.

Cette technique permet enfin de créer des applications client entièrement enJavaScript qui communiquent avec un serveur sans quitter la page courante, et doncen conservant la fluidité de l’interface. Fini le clignotement qui accompagnait lerechargement de la page HTML avec les technologies utilisant un submit HTML,on peut désormais construire des clients web qui autorisent un look-and-feel quasiidentique à celui d’un client lourd.

D’abord réservé à Internet Explorer, le support de XmlHttpRequest a rapidement étéincorporé dans les autres navigateurs, créant ainsi les conditions (avec DOM et CSS)pour la généralisation de ce nouveau type d’applications web riches et interactivesbaptisé AJAX (Asynchronous JavaScript and XML).

1.3 L’ÉTAPE SUIVANTE : GOOGLE WEB TOOLKIT

1.3.1 Les challenges

On l’a vu, au cours du temps les technologies mises en œuvre dans les applicationsweb ont évolué, se sont complexifiées et enrichies. Aujourd’hui, la réalisation d’uneapplication web dynamique de type AJAX suppose la maîtrise de JavaScript, de HTML,du DOM, et d’une ou plusieurs bibliothèques additionnelles.

JavaScript a longtemps été et est encore souvent considéré comme un langage descripting parmi d’autres. Cependant, JavaScript est un langage bien plus complexe etpuissant qu’on l’imagine souvent avant de l’étudier sérieusement. S’il est très faciled’ajouter un petit peu de dynamisme à une page web avec quelques lignes de JavaScript,son utilisation à plus grande échelle s’avère souvent problématique, et le passage austade industriel du développement est délicat...

Un des plus sérieux handicaps du développement AJAX est la nécessité de prendreen compte les différences entre les plates-formes pour obtenir un comportementidentique de l’application pour chacune d’elles. En effet, il existe entre les browsersmajeurs des variations considérables dans l’interprétation de JavaScript, le supportHTML, et la gestion du DOM. Ces différences ajoutent une charge de travailnon négligeable puisqu’il faut les connaître, savoir les contourner, implémenter lessolutions alternatives, tester pour les différentes plates-formes, etc. Ce type de dévelop-pement exige un niveau de compétences très pointu dans les domaines en question.

Page 24: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

10 Chapitre 1. De HTML à GWT

En outre, même si d’énormes progrès ont été faits dernièrement, les outils dedéveloppement JavaScript souffrent toujours de la comparaison avec leurs homologuesdes langages compilés comme Java ou C++, et sont souvent dédiés à une seule plate-forme cible. Les outils d’introspection HTML sont différents de Firefox à InternetExplorer et d’IE à Safari.

Enfin, le langage JavaScript, quelle que soit sa puissance, reste un langage interprétéet avec un typage faible ; de nombreuses erreurs n’apparaissent qu’à l’exécution, etleur diagnostic n’est pas toujours évident. Les possibilités de refactoring automatisé quisont devenues communes dans les environnements de développement intégré (IDE)Java ne sont encore qu’un rêve en JavaScript.

Pour toutes ces raisons, le développement AJAX « direct » en JavaScript, mêmes’il est attirant grâce aux résultats qu’il permet d’obtenir, présente des contraintesimportantes et des risques élevés.

1.3.2 Les réponses de GWT

Les problèmes posés par le développement AJAX n’ont bien sûr pas échappé àGoogle, dont de plus en plus d’applications ont mis en œuvre au fil du temps cettetechnologie. Google se devait donc de trouver des solutions à ses propres problèmesde développement JavaScript, et c’est de cette motivation qu’est né le Google WebToolkit.

Google s’est posé la question suivante : Quel langage de développement estaujourd’hui à la fois extrêmement répandu, mature, stable, disposant d’outils etd’environnements de développement complets et agréables à utiliser, et d’un potentielde compétences quasi inépuisable ? Si vous avez répondu Java, vous avez gagné biensûr.

Le postulat de base de GWT, qui peut sembler assez incongru de prime abord, estque le meilleur moyen de produire du JavaScript destiné à animer une application webn’est pas d’écrire directement le code JavaScript, mais d’utiliser un autre langage (Java),avec ses outils de développement et son environnement. L’écriture de l’application sefera entièrement en Java, avec tous les avantages : IDE complets et puissants, typagefort et vérifications statiques, aides au refactoring, débogage évolué, etc. Le codeJavaScript sera généré au besoin, pour déployer l’application ou pour la tester, à partirdu code Java.

Évidemment, les différences entre Java et JavaScript imposent des contraintes aucode qu’il est possible de transformer en JavaScript. Seule une partie des classes deJava SE est supportée, mais cela inclut la majorité des classes des packages java.langet java.lang.annotations, et une bonne partie de java.util. En pratique, il s’avèreque ces contraintes sont peu pesantes pour le développement courant.

De fait, le rôle joué par JavaScript dans une application GWT est similaire à celuide l’assembleur pour un langage de haut niveau, ou du bytecode pour une applicationJava standard : ce n’est ni plus ni moins qu’un langage intermédiaire destiné à êtreinterprété par une plate-forme cible.

Page 25: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

1.3 L’étape suivante : Google Web Toolkit 11

1.3.3 L’historique de la plate­forme

La première version distribuée publiquement de GWT, la version 1.0 RC1, a étépubliée en mai 2006. Elle a été annoncée au salon JavaOne la même année.

Chaque version majeure (1.1, 1.2) est en général précédée d’une « release candi-date » (RC), et parfois suivie de version corrective.

Les versions 1.1 et 1.2, publiées au cours de l’année 2006, ont introduit la plupartdes fonctionnalités qui existent dans la version actuelle. À noter que le support pourMac OS est présent depuis la version 1.2.

Un changement crucial est apparu avec la version 1.3 (février 2007), qui est lapremière version totalement Open Source de GWT. À partir de cette version, GWTest distribué sous la licence dite « Apache », qui est une des plus permissives du mondeOpen Source. Il s’agit là d’un gros argument de moins pour ceux qui doutaient de lapérennité de GWT comme produit purement propriétaire de Google.

La version 1.4 a introduit la plupart des composants graphiques existant dans laversion actuelle.

Un autre changement majeur a été introduit avec la version 1.5 (aout 2008) : ils’agit du support de la syntaxe Java 5, et principalement des types génériques. Jusquelà, GWT ne pouvait compiler que du code Java écrit avec la syntaxe Java 1.4 ; l’arrivéedes génériques a apporté un nouveau degré de vérifications statiques.

Puis la version 1.6 (avril 2009) a introduit deux changements principaux :

• une nouvelle structure de projet plus proche des standards du développementweb ;

• l’abandon de la notion de listener pour celle de handler.

La version 1.7, malgré son apparence de release majeure, n’apporte en fait essentiel-lement que la compatibilité avec Internet Explorer 8 et la version 10.6 de Mac OS X(« Snow Leopard »).

Enfin, la dernière version en date, qui porte le numéro 2.0, marque une étapeimportante grâce à de nombreuses nouveautés, axées principalement sur l’améliorationdes performances et l’optimisation. On y trouve en particulier :

• une nouvelle option permettant de déboguer avec tout type de navigateur ;• la possibilité de diviser le code en plusieurs blocs pour accélérer le chargement

initial ;• un langage de description permettant de construire des interfaces sans écrire de

code ;• le groupement de ressources hétérogènes, etc.

Un chapitre entier de cet ouvrage (chap. 12) est consacré aux nouveautés de cetteversion.

Vous pouvez consulter l’historique détaillé de GWT à cette adresse :http://code.google.com/webtoolkit/releases/release-notes-1.7.1.html.

Page 26: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 27: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Hello, GWT

2

ObjectifDans ce chapitre, nous installerons l’environnement de développement nécessaire àGWT ainsi que GWT lui-même, puis nous créerons notre premier projet GWT.

2.1 L’ENVIRONNEMENT DE DÉVELOPPEMENT

Une des caractéristiques de GWT est de ne pas imposer au développeur d’outilsspécifiques. Puisque le développement se fait en Java, pourquoi ne pas laisser ledéveloppeur utiliser son environnement de développement préféré ?

Et c’est en effet la réalité avec GWT : que vous soyez fan d’Eclipse, de NetBeansou d’IntelliJ, ou de tout autre IDE, le développement avec GWT ne se différencie quetrès peu du développement d’une application Java classique. On écrit du code Java,on le compile (ou l’IDE s’en charge automatiquement), on l’exécute et on le déboguedirectement comme n’importe quel code Java.

La différence la plus notable est sans doute que le code Java nécessite un environ-nement particulier pour s’exécuter : le hosted mode (ou mode hôte). Comme vous lesavez, le but ultime de GWT est de générer une application purement JavaScript, etqui s’exécute dans un navigateur web. Cependant, pour permettre le développementet surtout le débogage sous forme de code Java standard, le hosted mode permetd’exécuter l’application GWT dans sa version Java pur. La conversion en JavaScriptn’est nécessaire que pour le déploiement de l’application.

Page 28: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

14 Chapitre 2. Hello, GWT

Tab

leau

2.1

—Le

splu

gin

sde

GW

T

Plu

gin

Ver

sio

ns

de

GW

Tsu

pp

ort

ées

IDE

cib

leLi

cen

ceFo

nct

ion

nal

ités

Cyp

alSt

udio

for

GW

T1.0

1.4

,1.5

Eclip

se3.3

+G

ratu

itC

réat

ion

depr

ojet

/mod

ule

Cré

atio

nde

serv

ice

RPC

Lanc

emen

ten

mod

ehô

teC

ompi

latio

nJa

vaSc

ript

Dép

loie

men

tWA

R

Inst

antia

tions

GW

TD

esig

ner

7.2

1.4

,1.5

,1.6

,1.7

Eclip

se3.2

+C

omm

erci

alav

ecév

alua

tion

de14

jour

s(li

cenc

eco

mpl

ète

àpa

rtir

de59

$po

urun

an)

Edite

urvi

suel

d’in

terf

ace

Sync

hron

isat

ion

bidi

rect

ionn

elle

avec

leco

deJa

vaC

réat

ion

deco

mpo

sant

sré

utili

sabl

es

GW

TSt

udio

1.3

(Inte

lliJ

6)

1.4

(Inte

lliJ

7)

1.5

(Inte

lliJ

8)

1.6

,1.7

(Inte

lliJ

9)

Inte

lliJ

IDEA

Incl

usav

ecIn

telli

J(v

ersi

on6+)

Cré

atio

nde

proj

et/m

odul

eC

ompi

latio

nJa

vaSc

ript

Con

trôl

esst

atiq

ues

(insp

ect

ors

)La

ncem

enten

mod

ehô

teN

avig

atio

n/re

fact

orin

g/co

mpl

étio

nde

code

Dép

loie

men

tWA

R

GW

T4N

B1.5

,1.6

,1.7

Net

Bea

nsID

E6.7

.1G

ratu

itC

réat

ion

depr

ojet

Cré

atio

nde

serv

ice

RPC

Com

pila

tion

Java

Scrip

tD

éplo

iem

entW

AR

Goo

gle

Plug

info

rEc

lipse

Tout

es(le

télé

char

gem

entdu

plu

gin

incl

utla

vers

ion

lapl

usré

cent

ede

GW

T)

Eclip

se3.3

+G

ratu

itC

réat

ion

depr

ojet

/mod

ule/

entr

ypo

int/

page

hôte

Lanc

emen

ten

mod

ehô

teC

ompi

latio

nJa

vaSc

ript

Dép

loie

men

tsur

leG

oogl

eA

ppEn

gine

Vér

ifica

tion

synt

axiq

ueet

refa

ctor

ing

dans

les

mét

hode

sJS

NI

Page 29: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.2 Installation 15

2.1.1 Les plugins GWT

Bien entendu, il existe des plugins qui facilitent l’intégration de GWT dans les diffé-rents IDE. Le tableau 2.1 récapitule les caractéristiques des plugins GWT disponibles àce jour.

Deux plugins de cette liste nécessitent un approfondissement :

• GWT Designer est le seul qui offre la possibilité d’éditer visuellement uneinterface GWT. Néanmoins, c’est aussi le seul qui soit payant ;

• le dernier venu, le Google Plugin, est intéressant en premier lieu car il vientde Google lui-même, en deuxième lieu car il offre aussi la possibilité de testeret déployer des applications sur le Google App Engine dont la version Java estapparue simultanément.

Le plugin Cypal était jusqu’à l’apparition de GWT 1.6 le favori des utilisateursd’Eclipse, mais sa non-compatibilité avec GWT 1.6 et surtout l’apparition du GooglePlugin l’ont rendu obsolète.

2.2 INSTALLATION

2.2.1 Le choix de la plate­forme

Comme vous le savez, Java est par nature multi-plate-forme, et les outils associésexistent en règle générale pour la plupart des combinaisons architecture maté-rielle/système d’exploitation.

GWT lui-même, bien qu’étant quasi exclusivement écrit en Java, est publié parGoogle dans trois variantes :

• Windows (versions Vista, XP ou 2000) ;• Mac OS (versions 10.4 ou ultérieure) ;• Linux (x86, nécessite GTK+ version 2.2.1 ou ultérieure).

Bien entendu, il fallait faire le choix d’une plate-forme de référence pour illustrerles exemples de ce livre ; nous avons opté pour Eclipse 3.4 (« Ganymède ») sur MacOS X avec Google Plugin. À quelques différences mineures près, l’installation et ledéveloppement avec Eclipse et GWT sont tout à fait similaires sur les trois plates-formes ; nous signalerons toutefois les différences lorsque cela sera utile.

Nous détaillerons ici l’installation et l’utilisation de GWT uniquement en com-binaison avec Eclipse ; cependant si vous êtes familier d’un autre IDE, vous devriezfacilement réussir à transposer ces étapes pour votre IDE de prédilection.

Page 30: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

16 Chapitre 2. Hello, GWT

2.2.2 Installation d’Eclipse

Eclipse existe en de nombreuses variantes selon le type de développement qu’onsouhaite faire. La distribution qui nous intéresse doit au minimum intégrer ledéveloppement web, mais pour être paré nous utiliserons la version « JEE » qui inclutentre autres tous les outils web.

Cette version peut se télécharger depuis la page :

http://www.eclipse.org/downloads/packages/release/ganymede/sr2

Il n’existe pas d’installeur pour Eclipse (dans les versions standard) ; le télécharge-ment consiste simplement en un fichier ZIP qui contient un unique dossier eclipsequ’il suffit d’extraire à l’endroit le plus approprié (en principe C:\Program Files sousWindows, /Applications sous Mac OS). Simple et efficace.

Attention

Si vous faites une mise à jour d’une version existante, des précautions sont à prendrecar écraser simplement le dossier eclipse existant peut conduire à des mauvaisessurprises... Il est conseillé dans ce cas de suivre la procédure recommandée, qui estd’installer la nouvelle version à côté de l’existante, et de faire pointer la nouvelle versionvers le workspace existant.

Le dossier eclipse que vous venez d’extraire contient l’application elle-même, quis’appelle sans surprise eclipse.exe sous Windows ou Eclipse sous Mac OS. Libre àvous de créer alors un raccourci/alias où bon vous semble.

2.2.3 Installation de GWT

À noter

L’installation manuelle de GWT comme expliquée dans cette section n’est pasobligatoire si vous utilisez le Plugin Google ; en effet ce dernier inclut la versionla plus récente de GWT. Néanmoins, vous devrez procéder comme décrit ici si voussouhaitez travailler avec une version spécifique, ou installer simultanément plusieursversions de GWT.

GWT se télécharge depuis la page suivante :

http://code.google.com/webtoolkit/versions.html

Prenez soin de choisir la version correspondant à votre plate-forme de développe-ment.

Comme pour Eclipse, en téléchargeant GWT vous récupérez un fichier ZIP, quevous pouvez extraire à l’endroit qui vous semble le plus approprié. Sous Windows, vouspouvez créer un dossier C:\Java dans lequel vous placerez également toutes les autresbibliothèques Java. Sous Mac OS, l’emplacement le plus indiqué est /Library/Javapour une installation partagée, ou ~/Library/Java pour une installation personnelle(où ~ désigne votre home directory).

Page 31: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.2 Installation 17

Aucune installation additionnelle n’est à effectuer. Si vous examinez le contenudu dossier que vous venez d’extraire, vous y trouverez :

• des fichiers JAR qui contiennent les différentes parties de la bibliothèque GWTelle-même ;

• des scripts (fichiers .cmd dans la versions Windows, shell scripts dans la versionMac ou Linux) qui encapsulent différentes commandes utilitaires de GWT ;

• un sous-dossier doc contenant une partie de la documentation, à savoir laréférence de l’API GWT (la javadoc). À noter que le reste de la documentationest disponible uniquement en ligne ;

• des exemples prêts à être exécutés.

Un point de départ qui peut s’avérer utile est le fichier index.html dans le dossierprincipal de GWT qui contient des liens vers différentes ressources GWT sur le Web,la javadoc, les exemples, etc.

2.2.4 Google Plugin pour Eclipse

Le plugin GWT pour Eclipse de Google se trouve à l’adresse suivante :http://code.google.com/eclipse/

Si votre machine de développement est connectée à l’Internet, il est préférabled’utiliser le gestionnaire de téléchargements intégré à Eclipse pour installer ce plugin.

1. Démarrez Eclipse

2. Sélectionnez le menu Help/Software Updates...

3. Cliquez sur le bouton Manage Sites...

4. Cliquez sur le bouton Add...

5. Entrez l’URL du plugin : http://dl.google.com/eclipse/plugin/3.4 et validez avecOK.

6. Le site apparaît dans la liste comme « Google Update Site for Eclipse 3.4 ».Désélectionnez tous les sites à l’exception de celui-ci (ceci évite à Eclipse d’allervérifier des mises à jour inutiles, ce qui lui prend beaucoup de temps). Validezavec OK.

7. Acceptez la licence qui vous est proposée.

8. Laissez le téléchargement et l’installation se dérouler. S’il vous est proposé deredémarrer Eclipse pour prendre en compte les nouvelles fonctionnalités, il estpréférable d’accepter.

Page 32: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

18 Chapitre 2. Hello, GWT

2.3 ANATOMIE D’UN PROJET GWT

GWT inclut des utilitaires qui permettent de créer un squelette d’application GWTpouvant servir de base à un développement. Depuis GWT 1.6, le squelette ainsi créécontient même un exemple d’implémentation et d’utilisation d’un service distant(RPC).

Cependant, ce squelette est déjà relativement complexe pour aborder les conceptsGWT de base ; nous allons donc plutôt introduire les éléments de GWT plusprogressivement au travers d’un classique « Hello World » minimaliste.

2.3.1 Nommage des packages et structure des dossiers

Les applications GWT sont des projets particuliers car ce sont avant tout desapplications « web » au sens classique du terme, mais une fois chargées dans lenavigateur, elles se comportent comme des clients lourds.

La structure d’un projet GWT reflète cette dualité ; en effet il contient une partiequi doit être déployée de façon classique sur le serveur, à savoir les pages et fichiersstatiques ainsi que le code Java compilé (servlets par exemple), mais aussi le codeGWT qui lui doit être transformé en JavaScript par le compilateur GWT.

Pour matérialiser cette distinction, le code GWT doit se trouver dans un packageparticulier, par convention un sous-package nommé client. Par exemple, si lepackage principal de votre application est info.gerardin.monappli, le codeGWT dit « traduisible » (translatable code) doit se trouver dans le packageinfo.gerardin.monappli.client.

Pour le reste, fort heureusement le projet se structure comme un projet webclassique :

• le code source Java ainsi que les ressources associées se trouvent sous un dossiersource désigné (en principe src) ;

• les fichiers et pages statiques (HTML, JSP, ...) se placent dans un dossier war,qui servira de base à la création du fichier .WAR déployable ;

• dans ce dossier war, on trouve également un sous-dossier WEB-INF qui contientun certain nombre de ressources nécessaires au bon déploiement :

– le fichier web.xml permettant de configurer l’application et les éventuelsservlets,

– le sous-dossier lib contenant les bibliothèques Java utilisées (fichiers .JAR),

– le sous-dossier classes contenant les classes Java compilées et les ressources.

Le compilateur GWT placera également les fichiers générés dans un sous-dossierde war, de sorte qu’une fois le code Java classique compilé et le code GWT traduit enJavaScript, le dossier war soit prêt pour générer un fichier .WAR déployable.

Page 33: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.3 Anatomie d’un projet GWT 19

2.3.2 La page HTML hôte

Au final, le code GWT que vous allez écrire est destiné à tourner à l’intérieur d’unepage web sous forme de JavaScript. Par conséquent, même si votre application vaoccuper tout l’écran, il lui faut une page web pour l’accueillir : c’est ce qu’on appellela page HTML hôte (HTML host page).

Cette page hôte est une page HTML des plus classiques, à ceci près qu’elle doitfaire référence à un des fichiers JavaScript générés par le compilateur GWT au moyendu tag <SCRIPT>. Ce fichier sert de point d’entrée et va charger le reste du code GWTcompilé, ou plus précisément la version appropriée au navigateur sur lequel il vas’exécuter. Nous reviendrons sur ce mécanisme appelé « Deferred Binding », dans lechapitre 7.

Voici un exemple de page HTML hôte minimale :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>

<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Mon application GWT</title>

<script type="text/javascript" language="javascript"

src="monappli/monappli.nocache.js"></script>

</head>

<body></body>

</html>

Dans l’exemple ci-dessus, la ligne importante est la ligne en gras ; elle charge lescript JavaScript de bootstrap qui va initialiser toute la mécanique GWT. monapplidésigne le nom du module GWT qui contient la description de l’application (nous yreviendrons plus loin).

Comme vous le voyez, le contenu de la page peut rester totalement vierge ; dansce cas, c’est le code JavaScript qui créera tous les éléments visuels d’interaction via leDOM.

Cependant, GWT peut aussi s’intégrer facilement dans une page HTML existante :il suffit pour cela d’y ajouter l’élément <SCRIPT> obligatoire ; le code GWT peut alorsfaire référence à des éléments existants de la page au moyen de leur identifiant HTML(attribut id) pour y attacher des éléments additionnels, comme dans l’exemple pagesuivante.

Page 34: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

20 Chapitre 2. Hello, GWT

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>

<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Mon application GWT</title><script type="text/javascript" language="javascript"

src="monappli/monappli.nocache.js"></script></head>

<body><h1>Titre statique</h1>

<table align="center"><tr><td colspan="2" style="font-weight:bold;">URL:</td>

</tr><tr><td id="nameFieldContainer"></td><td id="sendButtonContainer"></td>

</tr><tr><td colspan="2" style="font-weight:bold;">Résultat :</td></tr><tr><td colspan="2" id="result"></td></tr>

</table></body>

</html>

Ici une partie de la page est construite par le HTML présent dans le fichier, le restesera généré par le code GWT.

Le cas échéant, si aucun des éléments n’est identifié, on peut toujours accéder à la« racine » de la page HTML et s’y « greffer » grâce à la méthode RootPanel.get().

2.3.3 Le point d’entrée

Tout comme une application Java classique, une application GWT possède un « pointd’entrée ».

Dans le cas d’une application Java classique, il s’agit d’une méthode public static

main(String args[]) dans une classe quelconque, que vous passez en paramètre à lacommande java pour démarrer l’application.

Dans le cas de GWT, il s’agit d’une méthode avec le profil public void onModule-

Load().

Contrairement à la méthode main décrite ci-dessus, onModuleLoad() n’est passtatic. En fait, la classe qui contient le point d’entrée doit implémenter l’interfacecom.google.gwt.core.client.EntryPoint, qui contient la seule méthode onModule-

Load(). Cela signifie qu’avant d’appeler onModuleLoad(), la classe doit être instanciéepar GWT ; à cet effet elle doit exposer un constructeur public sans arguments.

Page 35: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.3 Anatomie d’un projet GWT 21

Une autre différence importante avec une application classique : il est possible avecGWT de définir plusieurs points d’entrée. Ceux-ci seront déclarés dans la configurationdu module GWT, et lors de l’initialisation de GWT, chacune des classes déclaréescomme point d’entrée sera instanciée et sa méthode onModuleLoad() appelée.

2.3.4 Le fichier module

Jusqu’à présent, nous avons considéré une application GWT comme monolithique ;mais que se passe-t-il si on veut composer une application de plusieurs partiesindépendantes et réutilisables ? C’est pour cette raison qu’existe la notion de module.

Selon les propres termes de Google, un module est « l’unité de configuration »GWT. Cela signifie qu’un module comprend tout ce qui est nécessaire pour compiler,exécuter, déployer, réutiliser votre projet GWT.

Le module est défini au travers d’un fichier XML, dans lequel on trouvera enparticulier :

• la liste des classes contenant un point d’entrée à instancier ;• les modules « hérités » selon la terminologie GWT ; il s’agit en vérité des

modules utilisés par votre module (par exemple des bibliothèques de composantsexternes). À noter que les différents « thèmes » graphiques, c’est-à-dire l’ha-billage de base des composants, sont considérés comme des modules externes ;

• le source path, c’est-à-dire la liste des packages qui doivent être convertisen JavaScript lors de la compilation GWT. Les sous-packages d’unpackage du source path sont automatiquement inclus dans le source path ;par exemple si on désigne com.sfeir.gwt.client, les éventuels packagescom.sfeir.gwt.client.xxxxx seront aussi inclus dans le source path. Par défaut,le source path comprend le sous-package nommé client immédiatement endessous de l’endroit où se trouve le fichier XML du module.

Remarques

À propos du point d’entrée : Si le module GWT est destiné à être utilisé par d’autresmodules, il est parfaitement licite de ne définir aucun point d’entrée. En revanche, toutmodule référencé directement dans une page HTML (au travers de la balise SCRIPT)doit contenir au moins un point d’entrée.À propos du source path : Grâce à cette technique, il est parfaitement possible de« partager » certaines classes entre la partie « client » d’une application GWT (convertieen JavaScript) et le reste du code, notamment la partie serveur. Néanmoins, il fautgarder à l’esprit les contraintes qui pèsent sur le code convertible (voir § 3.2 Contraintessur le code Java).

Le fichier de module a un suffixe .gwt.xml. Il peut se trouver n’importe où dans leclasspath du projet, mais il est conseillé de le placer dans le package racine de votreprojet.

Page 36: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

22 Chapitre 2. Hello, GWT

Voici un exemple de fichier module tel que généré par GWT :

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN""http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd"><module rename-to=’gwtskel’>

<!-- Inherit the core Web Toolkit stuff. --><inherits name=’com.google.gwt.user.User’/>

<!-- Inherit the default GWT style sheet. You can change --><!-- the theme of your GWT application by uncommenting --><!-- any one of the following lines. --><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’/> -->

<!-- Other module inherits -->

<!-- Specify the app entry point class. --><entry-point class=’oge.gwt.skel.client.GwtApp’/>

</module>

L’attribut rename-to de l’élément module est important, car il permet de définirun « alias » au nom logique du module, qui est utilisé en particulier comme dossierde base pour tous les fichiers générés par la compilation JavaScript. En l’absence derename-to, le nom du module est le nom du package dans lequel il se trouve suivide son nom (sans .gwt.xml) ; par exemple, si le module se trouve dans le fichierGwtSkeleton.gwt.xml, situé dans le package oge.gwt.skel, le nom logique du moduleest oge.gwt.skel.GwtSkeleton. Avec l’attribut rename-to de notre exemple, le nomlogique du module devient gwtskel.

2.4 HELLO, GWT

Nous allons maintenant assembler les éléments vus ci-avant (page hôte, module, pointd’entrée) et construire un premier projet GWT minimaliste, au moyen d’Eclipse et deGoogle Plugin.

2.4.1 Création du projet

Dans Eclipse, créez un nouveau projet : Menu File > New... > Projet.

Une liste de types de projets vous est proposée ; choisissez Dynamic Web Projectpuis cliquer sur Next (figure 2.1).

Donnez un nom au projet (« GwtChap24Hello » par exemple), et laissez les autresparamètres à leur valeur par défaut. Cliquez sur Next (figure 2.2).

Page 37: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.4 Hello, GWT 23

Figure 2.1 — Choix du type de projet

Figure 2.2 — Options de création

Page 38: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

24 Chapitre 2. Hello, GWT

Dans l’écran suivant, spécifiez « war » comme valeur pour Content Directory. Ceciest important pour que les réglages d’Eclipse correspondent à ceux de GWT. Cliquezsur Finish (figure 2.3).

Figure 2.3 — Options du module web

2.4.2 Création du module GWT

Le projet est maintenant créé, il reste à activer le Google Plugin pour ce projet. Pourcela, faites un clic droit sur le projet puis sélectionnez Google > Web Toolkit Settings.Dans la fenêtre qui s’ouvre, cochez la case Use Google Web Toolkit, et sélectionnez laversion à utiliser. Cliquez sur OK (figure 2.4).

Créez un package racine pour le projet : clic droit sur le projet puis sélectionnezNew > Package. Nommez-le par exemple oge.gwt.chap24.hello, puis cliquez sur Finish(figure 2.5).

On va maintenant créer un module GWT : clic droit sur le projet, puis sélectionnezNew > Other...

Page 39: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.4 Hello, GWT 25

Figure 2.4 — Propriétés GWT du projet

Figure 2.5 — Création d’un nouveau package

Page 40: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

26 Chapitre 2. Hello, GWT

Dans la fenêtre qui s’ouvre, choisissez Google Web Toolkit > Module puis cliquez surNext (figure 2.6).

Figure 2.6 — Création d’un nouveau module GWT

Dans l’écran suivant (New GWT Module) :

• cliquez sur Browse en face de Package et sélectionnez la package que vous avezcréé ci-avant ;

• dans Module Name, donnez un nom à votre module, par exemple HelloGwt

(figure 2.7) ;• cliquez sur Finish ; le fichier module HelloGwt.gwt.xml est créé et ouvert. Vous

pouvez noter que le sous-package client a été créé automatiquement.

Figure 2.7 — Options de création du nouveau module

Page 41: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.4 Hello, GWT 27

2.4.3 Création du point d’entrée

On doit créer au minimum une classe avec un point d’entrée pour initialiser l’applica-tion. Pour cela, faites un clic droit sur le projet et New > Other...

Dans la fenêtre qui s’ouvre, choisissez Google Web Toolkit > Entry Point class puiscliquez sur Next (figure 2.8).

Figure 2.8 — Création d’un point d’entrée

Dans l’écran suivant, donnez un nom à la classe : HelloGwt et laissez les autresparamètres par défaut. Cliquez sur Finish (figure 2.9).

Figure 2.9 — Options de création du point d’entrée

Page 42: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

28 Chapitre 2. Hello, GWT

Vous pouvez noter qu’une ligne référençant le point d’entrée a été ajoutée dans lefichier module. Pour vérifier que le point d’entrée est bien invoqué, ajoutez la lignesuivante dans la méthode onModuleLoad() de la classe qui vient d’être créée :

RootPanel.get().add(new Label("Ca marche !"));

2.4.4 Création de la page HTML hôte

Reste à créer la page HTML hôte : clic droit et New > Google Web Toolkit > HTMLPage puis Next (figure 2.10).

Figure 2.10 — Création d’une page HTML hôte pour GWT

Donnez un nom à la page : Hello.html. Laissez les autres paramètres par défaut etcliquez sur Finish (figure 2.11).

Figure 2.11 — Options de création de la page

Page 43: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

2.4 Hello, GWT 29

2.4.5 Lancement de l’application

Voilà, tout est en place... Pour lancer l’application, il suffit de faire un clic droit puisde sélectionner Run As > Web Application ; si tout est correct, l’application se lanceen hosted mode, ce mode spécial qui permet d’exécuter le code Java GWT sans letransformer en JavaScript (nous y reviendrons dans le chapitre suivant).

Vous devriez voir la fenêtre « shell » du mode hôte présentée en figure 2.12, et lafenêtre « navigateur » qui affichera la page hôte et au final notre label, en figure 2.13.

Figure 2.12 — Fenêtre shell du hosted mode

Figure 2.13 — Fenêtre navigateur

Certes cette première application GWT ne fait pas grand chose d’utile, maisl’infrastructure est en place pour commencer à coder...

Page 44: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 45: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Développer avec GWT

3

ObjectifLe développement avec GWT est sensiblement différent du développement Javastandard, de par la nature de l’environnement ciblé (navigateur web). Dans cechapitre, nous allons voir quelles sont les différences avec le développement Javastandard et comment GWT permet au développeur de travailler au quotidien.

3.1 HOSTED MODE VS WEB MODE

À la fin du chapitre précédent, nous avons lancé notre application minimalisteau travers d’une configuration de lancement (launch configuration) créée pour nousautomatiquement par le Google Plugin. Nous avons vu que cette application s’estexécutée dans une fenêtre intitulée « Google Web Toolkit hosted mode ».

En réalité, le « mode hébergé » (hosted mode) est une des deux façons d’exécuterune application GWT : dans ce mode, c’est le code Java compilé (bytecode) quis’exécute directement dans une JVM (Java Virtual Machine, machine virtuelle Java)comme pour une application classique. Cependant, il ne s’agit pas d’une applicationclassique puisqu’elle est destinée au final à être utilisée dans un navigateur web ; leprincipe même est que toute son interface utilisateur repose sur la création et lamanipulation de la page HTML au travers de l’API DOM.

Comment alors cette application peut-elle s’exécuter directement en Java ? Lehosted mode embarque en fait un moteur de rendu HTML comme celui qu’on trouvedans les navigateurs web, à ceci près qu’il est spécialement modifié pour pouvoirexécuter nativement le code Java compilé, là où un navigateur classique ne comprend

Page 46: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

32 Chapitre 3. Développer avec GWT

que le JavaScript. Dans la version Windows de GWT, ce moteur est celui d’InternetExplorer ; dans la version Mac, il s’agit de WebKit, le moteur de base de Safari, etdans la version Linux, une version modifiée de Mozilla.

L’exécution d’une application GWT en hosted mode a un énorme avantage : commeil s’agit de pur Java, il est possible de positionner des points d’arrêt (breakpoints) là oùon le désire, de démarrer l’application en mode debug, de faire de l’exécution en pas àpas, d’examiner le contenu des variables, etc. Toutes choses que quiconque s’est essayéà la programmation JavaScript directe appréciera... À noter que si votre applicationcomprend une partie serveur (ce qui sera très probablement le cas), ceci s’appliqueaussi au code serveur, pour peu que le serveur soit aussi du code Java qui puisse tourneren mode debug. La plupart des IDE Java fournissent une bonne intégration avec lesserveurs d’application et facilitent cet usage.

Autre intérêt non négligeable : après une modification du code, un simple clic sur lebouton Refresh du navigateur hosted mode recharge l’application avec les modifications.Ceci autorise des cycles codage/test courts, car la compilation en JavaScript n’est pas,elle, des plus rapides.

Le postulat central de GWT, c’est que si votre application fonctionne commeattendu en mode hôte, alors après sa compilation en JavaScript elle se comporteraexactement de la même manière dans les navigateurs supportés (et à quelques excep-tions près, c’est généralement le cas). Par conséquent, en tant que programmeur GWTvous passerez probablement la plupart de votre temps à exécuter votre application enmode hôte, et ne la compilerez en JavaScript que de temps en temps pour vérifier quetout fonctionne comme prévu sur la plate-forme finale.

3.2 CONTRAINTES SUR LE CODE JAVA

Le principe même de GWT, c’est-à-dire le fait que le code que vous écrivez ne serapas le code final qui sera exécuté dans le navigateur, mais qu’il devra passer parune étape de transformation en JavaScript et ne tournera pas dans une JVM maisdans un interpréteur JavaScript, impose certaines contraintes et limitations lors dudéveloppement. Ces contraintes portent sur le langage lui-même, ainsi que sur lesclasses du Java Runtime Environment (JRE, environnement d’exécution Java) qui sontutilisables.

3.2.1 Support du langage

Lorsque vous développez le code client d’une application GWT, l’ensemble despossibilités du langage Java est disponible, y compris l’utilisation des génériques, desannotations et plus généralement des nouveautés apportées par Java 5.

Cependant, il faut garder à l’esprit que la cible est JavaScript, et certaines carac-téristiques de Java ne disposent pas d’équivalent en JavaScript. Parmi les principalesdifférences qui sont les plus susceptibles de nécessiter une attention particulière, onpeut citer les suivantes.

Page 47: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

3.2 Contraintes sur le code Java 33

• Mono-thread : Le modèle d’exécution de JavaScript est mono-thread (un seul fild’exécution), et donc votre application le sera aussi. Le mot-clé synchronized

est accepté par le compilateur GWT, mais n’a aucun effet. De même, il estimpossible de démarrer un nouveau thread via la classe Thread. Cette limitationaura des conséquences importantes sur la façon d’accéder à des services distants(RPC).

• Pas de réflexion : Java permet de charger une classe dynamiquement àl’exécution, par exemple grâce à Class.forName(), et l’instancier grâce àClass.newInstance() ; cette possibilité n’existe pas en JavaScript, car latotalité des classes utilisées doit être connue par le compilateur GWT aumoment de la compilation. Attention, car cela peut sembler fonctionner trèsbien en mode hôte, et ce n’est que lors de l’exécution en mode web que celaproduira une erreur. De même, il est impossible dans le code client d’énumérerles propriétés ou méthodes d’une classe.

• Gestion des exceptions : Le support des exceptions est similaire à celui deJava, avec toutefois quelques différences notables. En particulier, certainesexceptions non contrôlées (unchecked) comme NullPointerException, StackO-verflowException ou OutOfMemoryException ne sont jamais levées dans le codeJavaScript ; à la place une exception générique JavaScriptException est levée.Les valeurs qui pourraient être nulles doivent donc être testées explicitement(comme ça devrait être toujours le cas en bon Java...). D’autre part, l’exceptionlevée en JavaScript est relativement pauvre en informations ; getStackTrace()par exemple ne retourne malheureusement rien de très exploitable, ce qui peuts’avérer gênant dans le cas où une exception se produit dans la version JavaScriptde votre code mais pas dans sa version Java... heureusement ce cas est rarissime.

• Support partiel de long : le type long n’est pas supporté en JavaScript ;cependant cela n’est pas un problème dans le code qui est compilé en JavaScript,car le compilateur GWT gère cela de façon totalement transparente (grâce à unepaire d’int) ; il faut toutefois en être conscient lorsqu’il s’agit de communiqueravec du JavaScript natif via JSNI.

• Pas de support de finalize : JavaScript ne supporte pas la finalisation durantle passage du ramasse-miettes (garbage collector) ; par conséquent, la méthodefinalize n’est jamais exécutée.

3.2.2 Émulation des classes du JRE

Le code Java qu’on peut écrire utilise en permanence, qu’on en soit conscient ou non,des classes et des méthodes qui font partie de la bibliothèque de base du JRE. Cesclasses sont celles qui permettent de manipuler les objets natifs tels que String ouInteger, mais aussi les exceptions, les collections, etc.

Pour pouvoir exécuter en JavaScript l’équivalent de ce que votre code Javaeffectue avec ces classes, le code JavaScript doit pouvoir accéder à un équivalent dela bibliothèque de base du JRE ; c’est le rôle que remplit la bibliothèque d’émulationJRE de GWT. Cette bibliothèque consiste en un ensemble de classes JavaScript,qui reproduit (« émule ») de façon aussi précise que possible le comportementde leurs équivalents du JRE, dans les limites que permet JavaScript.

Page 48: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

34 Chapitre 3. Développer avec GWT

Sont compris dans cette bibliothèque :

• la quasi totalité du package java.lang, qui comprend l’essentiel des classes debase de Java, ainsi que java.lang.annotation ;

• une grande partie du package java.util, y compris les collections ;• quelques classes des packages java.io et java.sql. Il n’est toutefois pas question

d’écrire des fichiers ou d’accéder à une base SQL, mais simplement de faciliterla compatibilité.

Classes émulées

La table accessible en annexe 1 contient la liste des classes présentes dans la biblio-thèque d’émulation JRE de GWT. Attention, dans certains cas, seul un sous-ensembledes méthodes de la classe est implémenté. La liste complète des méthodes peut êtreconsultée sur la page :

http://code.google.com/webtoolkit/doc/1.6/RefJreEmulation.html

Autres différences

Il existe d’autres domaines pour lesquels l’émulation de GWT diffère du Java standard :

• le support des expressions régulières (regexp) est légèrement différent entre Javaet JavaScript ; GWT ne cherche pas à reproduire pas en JavaScript le comporte-ment des expressions régulières Java, mais s’appuie sur l’implémentation nativede JavaScript. Ceci s’applique notamment aux méthodes String.replaceAll()et String.split(). Il convient donc lorsqu’on appelle ces méthodes de s’assurerqu’on utilise des expressions régulières qui ont la même sémantique en Java eten JavaScript ;

• la notion de sérialisation en Java s’appuie fortement sur la réflexion qui, onl’a vu, n’est pas disponible en JavaScript. La sérialisation Java n’est donc pasutilisable dans le code client ; cependant, un mécanisme similaire existe dans lebut d’invoquer des méthodes distantes via RPC (voir le chapitre 5 à ce sujet).

Classes utilitaires

Pour certaines classes du JRE dont l’émulation aurait été trop coûteuse, GWT fournitun équivalent « light » qui offre une fonctionnalité similaire mais simplifiée :

• com.google.gwt.i18n.client.DateTimeFormat supporte un sous-ensemble dela fonctionnalité de java.util.DateTimeFormat ;

• com.google.gwt.i18n.client.NumberFormat supporte un sous-ensemble de lafonctionnalité de java.util.NumberFormat ;

• com.google.gwt.user.client.Timer fournit une fonctionnalité similaire àjava.util.Timer, adaptée à l’environnement mono-thread.

L’utilisation des classes DateTimeFormat et NumberFormat est détaillée au § 6.3 Leformatage des dates et nombres.

Page 49: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

3.3 Lancer en mode hôte 35

3.3 LANCER EN MODE HÔTE

Le hosted mode est implémenté dans la classe com.google.gwt.dev.HostedMode, quise trouve dans le fichier gwt-dev-mac.jar (ou gwt-dev-windows.jar ou gwt-dev-

linux.jar, selon votre plate-forme de développement). Pour démarrer une applicationGWT en mode hôte, il suffit d’exécuter une commande de la forme :

java -XstartOnFirstThread com.google.gwt.dev.HostedMode -startupUrlHelloGwt.html HelloGwt.gwt.xml

HelloGwt.gwt.xml désigne le module principal de votre application, qui contienttoutes les informations nécessaires à l’exécution. Le paramètre startupUrl quant àlui désigne une page web à ouvrir au démarrage, normalement la page hôte de votreapplication. Bien sûr, pour que cette commande fonctionne, le classpath doit inclure leJAR gwt-dev-xxx.jar, ainsi que tout le code client, en particulier le fichier de module.

Heureusement, il existe des façons plus simples de lancer une application en modehôte. Comme nous l’avons vu dans le chapitre précédent, le Google Plugin ajoute àEclipse un type de run configuration (configuration d’exécution) qui permet de démarrerune application GWT très facilement depuis Eclipse.

Figure 3.1 — Configurations d’exécution GWT dans Eclipse

En outre, lorsque vous générez un squelette d’application au travers du mêmeplugin, la configuration d’exécution est créée automatiquement pour vous. De mêmeau travers de l’outil en ligne de commande webAppCreator inclus dans GWT, quigénère en prime un fichier build.xml destiné à Ant, ce fichier comprend une cible(target) nommée « hosted » qui démarre l’application en hosted mode.

Page 50: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

36 Chapitre 3. Développer avec GWT

3.3.1 Le serveur d’applications intégré

Même s’il est parfaitement possible de créer une application GWT « stand-alone », laplupart des applications GWT auront besoin tôt ou tard de communiquer avec unserveur pour réaliser certaines opérations. Pour cette raison, le mode hôte de GWTembarque un serveur d’applications qui permet de tester facilement à la fois le codeclient (qui tourne dans le navigateur) et le code serveur (qui tourne en principe dansun serveur web) en un seul environnement, ce qui est très commode.

Depuis la version 1.6, le serveur embarqué est Jetty, qui succède à Tomcat dansles versions précédentes. Jetty est un serveur web et un moteur de servlets adaptéaux configurations embarquées grâce à son faible besoin en mémoire, et offrant desperformances comparables. Dans la pratique, peu de différences sont perceptibles, carles deux implémentent la spécification « Java Servlets 2.5 ». Nous reviendrons sur ledéveloppement de code serveur dans le chapitre 5.

Notez toutefois que sur des projets conséquents, il arrive fréquemment que la partieserveur d’un projet ne puisse pas fonctionner dans le serveur embarqué avec le hostedmode ; ceci arrive en particulier dès qu’on a besoin de faire appel à des fonctionnalitésavancés spécifiques à un serveur d’applications, typiquement lorsqu’on met en jeudes mécanismes transactionnels ou des Entity JavaBeans (EJB). Dans ce cas, il suffitde décocher l’option Run built-in server dans l’onglet principal de la configurationd’exécution GWT, ou bien de passer l’option -noserver sur la ligne de commande quidémarre le mode hôte ; ainsi le serveur intégré ne démarrera pas.

3.4 COMPILER ET LANCER EN MODE WEB

Lorsque vous voulez tester une application GWT comme si elle était déployée, c’est-à-dire sous forme de JavaScript dans un navigateur classique, il faut passer par l’étape de« compilation GWT », dont le but est de générer le code JavaScript correspondant aucode Java que vous avez écrit.

Cette opération est parfois nécessaire lorsque vous voulez contrôler les perfor-mances de votre application dans un navigateur natif ; en effet, en hosted mode votreapplication est exécutée sous forme d’un mélange de code Java natif (votre propre code,les bibliothèques GWT et les éventuelles bibliothèques tierces) et de JavaScript (parexemple, les bibliothèques JavaScript intégrées directement dans la page HTML). Cetenvironnement étant très différent de l’environnement cible (JavaScript seulement),il peut exister des différences de performance importantes entre les deux, dans unsens comme dans l’autre. En général, on constate que le code orienté « interfaceutilisateur » est sensiblement plus performant en web mode qu’en hosted mode, maiscela peut varier dans un sens comme dans l’autre.

Une option simple pour tester l’application en mode web est de cliquer sur lebouton Compile/Browse du navigateur du mode hôte ; ceci a pour effet de déclencherla compilation JavaScript, et lorsque celle-ci est terminée, ouvre la page hôte dans lenavigateur par défaut de votre système. Cette possibilité est intéressante car elle nenécessite aucun paramétrage, mais elle a comme inconvénient de ne pas pouvoir être

Page 51: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

3.4 Compiler et lancer en mode web 37

intégrée dans une chaîne de construction automatisée, et de bloquer le mode hôtedurant tout le temps de la compilation. Heureusement, d’autres options sont offertes.

Figure 3.2 — Bouton Compile/Browse du navigateur du mode hôte

Le compilateur GWT est implémenté dans la classe com.google.gwt.dev.Compiler,qu’on peut appeler depuis une ligne de commande de la façon suivante :

java com.google.gwt.dev.Compiler Hello.gwt.xml

Si le projet a été généré par l’outil webAppCreator, une cible ant spécifiquenommée gwtc (qui est également la cible par défaut) est incluse dans le fichierbuild.xml généré, de sorte que l’appel à la commande :

ant gwtc

ou tout simplement :

ant

va déclencher la compilation GWT.

3.4.1 Les fichiers générés par le compilateur GWT

Pour exprimer les choses très simplement, le but du compilateur GWT est de générerune application JavaScript équivalente à votre application Java. Il va donc examinervotre code source et générer un ensemble de fichiers aux noms cryptiques quicontiennent le code JavaScript et d’autres ressources nécessaires au fonctionnementde l’application en mode web.

La compilation GWT n’est pas une opération simple ; en effet le compilateurdoit prendre en compte les différentes plates-formes cibles pour générer du codequi fonctionne à l’identique sur toutes celles-ci. Plutôt que de générer un seul code

Page 52: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

38 Chapitre 3. Développer avec GWT

JavaScript et d’y inclure des tests pour s’adapter au navigateur, les développeurs deGWT ont pris le parti de générer une variante de code JavaScript par plate-formecible. Le fichier qui est référencé dans la page HTML hôte ne sert qu’à détecterla plate-forme courante, et passer la main au code JavaScript spécifique à celle-ci.Cette approche est nettement plus performante car elle réduit le volume du codeà télécharger, et rend inutile tout test de plate-forme ultérieur. En contrepartie, laphase de compilation est plus longue puisqu’il faut générer autant de variantes que deplates-formes supportées (cinq pour GWT 1.6/1.7).

Le compilateur GWT crée (normalement sous le dossier war) un sous-dossier parmodule, portant le nom du module. Dans chacun de ces dossiers, on retrouvera uncertain nombre de fichiers aux noms peu évocateurs, par exemple :

testapp/14A43CD7E24B0A0136C2B8B20D6DF3C0.cache.png

testapp/29F4EA1240F157649C12466F01F46F60.gwt.rpc

testapp/346766FA9D2CAEC39CC4D21F46562F34.cache.html

...

testapp/FCF795F77D04980E723A4DFA05A7926B.cache.html

testapp/FDFBC219465FCAB905EA55951EE425FA.cache.html

testapp/clear.cache.gif

testapp/hosted.html

testapp/testapp.nocache.js

Ces fichiers contiennent les différentes variantes de code généré pour chacunedes plates-formes cibles. Le seul fichier qui nous intéresse véritablement ici est lefichier testapp.nocache.js (où testapp est le nom de votre module), qui contient lebootstrap, c’est-à-dire le minimum de code qui va déterminer la plate-forme couranteet charger les fichiers adéquats. C’est ce fichier que vous devrez référencer dans la pageHTML hôte de votre application (voir § 2.3.2 La page HTML hôte).

3.5 DÉVELOPPEMENT AVEC L’IDE

Lorsque vous développez avec GWT, il y a fort à parier (nous l’espérons !) que voustravaillerez depuis un IDE tel Eclipse. Dans ce cas, comment se passe l’intégration devotre projet GWT dans l’IDE ?

Tout d’abord, pour l’IDE, un projet GWT est un projet Java comme un autre : il estconstitué de code source Java qui sera compilé en bytecode, et de ressources qui serontcopiées telles quelles. Dans les IDE modernes (y compris Eclipse), la compilation estincrémentale et se produit au fur et à mesure que vous sauvegardez le code source ; iln’est pas utile de déclencher manuellement une compilation. Par conséquent, votreprojet est toujours prêt à être lancé en hosted mode, pour peu que vous ayez défini uneconfiguration d’exécution appropriée.

Page 53: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

3.5 Développement avec l’IDE 39

3.5.1 Debug et cycle de développement

Comme toute application Java, une application GWT peut également être démarréeen mode debug. C’est ici que GWT montre tout son intérêt, puisque vous pouvezutiliser votre IDE favori (Eclipse, IntelliJ, Netbeans ou autres) pour positionner despoints d’arrêt dans le code Java, et utiliser toutes les fonctionnalités du débogueurintégré que vous utiliseriez pour une application Java : inspecter le contenu desvariables, avancer en pas à pas, etc. Il est loin d’être aussi aisé de faire la même choseen JavaScript.

Une fois votre application démarrée en hosted mode, vous serez naturellementamené à modifier (et donc recompiler) votre code. En principe, si l’application a étélancée en mode debug par l’IDE, ce dernier tentera de recharger la nouvelle versiondes classes dans la JVM en cours d’exécution (hotswap). Dans une application Javaclassique, cela fonctionne dans un certain nombre de cas, avec certaines limitations(pas de modification du profil de la classe par exemple) ; en pratique dans uneapplication GWT cela ne fonctionne pas à cause des spécificités du hosted mode. Faut-ilen conclure qu’après chaque modification du code, il faut relancer complètement lehosted mode ? Heureusement non, les concepteurs de GWT ont prévu ce cas : la fenêtreprincipale du hosted mode est pourvue d’un bouton Reload qui a pour effet de rechargerl’application, sans pour autant redémarrer le hosted mode.

Figure 3.3 — Bouton Reload du navigateur du mode hôte

La plupart du temps, il est donc commode de laisser les fenêtres du hosted modeouvertes en parallèle à l’IDE ; lorsque des modifications sont à tester, on bascule versle hosted mode et on recharge l’application via le bouton Reload.

Page 54: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

40 Chapitre 3. Développer avec GWT

Figure 3.4 — Résumé du cycle de développement

Attention toutefois à certains points :

• Si votre application possède une partie serveur déployée sur un serveur web horsdu hosted mode et que vous intervenez sur le code de cette partie serveur, il faudraredéployer vos modifications sur le serveur web. Exception : si le serveur estdémarré en mode debug depuis l’IDE et que vos modifications sont compatiblesavec le hotswap de la JVM, elles seront prises en compte sans redéploiement.

• Si votre application accède à des ressources générées lors de la compilationGWT, il pourra s’avérer nécessaire de relancer la compilation GWT.

• Après un certain temps d’utilisation, on constate que le hosted mode devient deplus en plus lent. Fuite mémoire ? En tout cas, un simple redémarrage remet leschoses en ordre.

Page 55: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Widgets, panels, etc.

4

ObjectifUn des aspects les plus attractifs de GWT est la possibilité de construire une interfacegraphique dynamique à base de composants de type « widgets » qu’on trouve dansdes toolkits comparables comme Swing. Nous allons voir dans ce chapitre quelscomposants offre GWT et comment les combiner dans des panels.

4.1 UNE INTERFACE GRAPHIQUE DYNAMIQUE

Même si on ne peut pas le résumer à cela, la caractéristique le plus souvent mise enavant de GWT est la possibilité de construire une interface homme-machine (IHM,ou Graphical User Interface GUI) dynamique. Qu’est-ce qu’une interface dynamique ?Pour simplifier, on peut dire que c’est une interface :

• polymorphe, c’est-à-dire qui présente à l’utilisateur des aspects variables (parexemple, un nœud d’un arbre peut être développé ou réduit) ;

• réactive, c’est-à-dire qui produit un feedback instantané aux actions de l’utilisa-teur (par exemple, montrer par un indicateur que le champ en cours de saisien’est pas valide).

Page 56: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

42 Chapitre 4. Widgets, panels, etc.

Comme nous l’avons évoqué au début de ce livre, les interfaces web « tradition-nelles » sont loin d’être dynamiques, pour deux raisons principales :

• la pauvreté des composants de base : même s’ils se sont enrichis au cours dutemps, la base des applications web a longtemps été le formulaire avec seschamps texte et un bouton submit. Même avec des composants additionnelscomme la case à cocher ou la liste déroulante, les possibilités restent limitées ;

• l’impossibilité de fournir un feedback tant qu’une requête n’a pas été soumiseau serveur. Outre le délai que cela induit, la page doit être rechargée en entier.

La combinaison de JavaScript (pour l’aspect réactif) avec DOM/DHTML etCSS (pour l’aspect polymorphe) a finalement offert les mécanismes nécessaires àla création de véritables interfaces dynamiques au sein d’une page web ; GWT offreune abstraction de ces mécanismes derrière une architecture de composants similairesà ce qu’offrent les toolkits d’IHM classiques tel Swing ou SWT.

4.1.1 Les widgets GWT

Comme pour les toolkits classiques, une IHM construite avec GWT consiste enun assemblage de composants, appelés « widgets » dans la terminologie officielle.Cependant, à la différence d’un toolkit classique, les widgets GWT sont rendus àl’écran au travers de HTML généré dynamiquement, au lieu de graphismes dessinés.

Un des partis pris de GWT est d’utiliser les composants HTML natifs à chaquefois que c’est possible ; par exemple le widget TextBox sera rendu par un élémentHTML <input>, Button par un <button>. Cela a plusieurs avantages : rapidité, légèreté,accessibilité, et un rendu familier qui ne déroute pas les utilisateurs. En revanche,d’autres composants seront rendus synthétiquement au travers de bitmaps et de <div>.

La façon précise dont un widget est rendu peut dépendre de la plate-forme cible,mais là encore c’est totalement transparent pour le programmeur et en pratique unwidget se comportera de la même façon sur les différents navigateurs.

4.1.2 GWT et les aspects graphiques

Alors que les toolkits classiques s’appuient sur des API permettant de définir lesattributs des composants (couleur, trait, police, etc.), il aurait été très complexe demettre en œuvre une telle stratégie dans un toolkit comme GWT qui, au final, produitdu HTML. Au lieu de cela, GWT a adopté une approche plus simple et plus naturelle,puisque tous les aspects de stylisation de GWT reposent sur l’utilisation de styles CSS.L’association de styles aux widgets se fait simplement dans le code GWT au travers deméthodes comme addStyleName() ou removeStyleName().

Cette approche a l’avantage de séparer clairement la logique applicative des aspectsde design, ce qui facilite le travail collaboratif puisqu’il est plus aisé de travaillerindépendamment sur l’un et sur l’autre. En outre, cela offre de meilleures performanceset permet de faire des modifications de style sans recompiler l’application.

Page 57: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 43

4.2 WIDGETS ET PANELS

Les widgets GWT peuvent être rangés en deux catégories : les widgets simples, et lespanels, ces derniers ayant la caractéristique de pouvoir contenir d’autres widgets (onreconnaît là le fameux design pattern « composite »). La construction d’une interfaceutilisateur se fait habituellement – comme pour les bibliothèques d’IHM classiques –par composition, en instanciant des widgets et en les ajoutant à des panels.

Le rôle d’un widget est de permettre l’interaction avec l’utilisateur, que ce soitsimplement en affichant un texte (Html), en réagissant à un clic (Button), en autorisantla saisie de texte (TextBox), etc. Par contraste, le rôle d’un panel est de gérer ladisposition (layout) de ses enfants, c’est-à-dire des widgets qu’il contient.

Widget gallery

Le « catalogue » des widgets et panels GWT est visible sur la pagehttp://code.google.com/webtoolkit/doc/1.6/RefWidgetGallery.html avec desexemples pour chacun d’entre eux. Il peut être utile de garder ce lien dans ses favoriscomme référence en ligne.

4.2.1 Événements et Handlers

Le concept d’événement est central dans le fonctionnement des widgets GWT,puisqu’il permet la réactivité de l’interface. Un événement est généré lorsqu’unesituation particulière se produit, par exemple un clic de l’utilisateur sur un bouton.

Pour qu’un événement puisse déclencher une action, il doit être associé à un handler.Concrètement, un handler est une interface qui définit une ou plusieurs méthodes quele widget appellera lorsque l’événement correspondant se produira. Par exemple, pourdéclencher une action sur un clic, il faut implémenter l’interface ClickHandler quicontient une unique méthode onClick(ClickEvent). Le widget Button génère desévénements de type Click (il implémente HasClickHandlers), on peut donc lui fournirune instance de ClickHandler via la méthode addClickHandler() ; chaque fois quel’événement se produira, le widget appellera la méthode onClick() du ClickHandler

qu’on lui aura fourni.

À titre d’exemple, voici comment associer un ClickHandler à un Button :

class MyHandler implements ClickHandler {/*** appelé lorsque l’utilisateur clique sur le bouton.*/

public void onClick(ClickEvent event) {// Faire quelque chose...}

}

// Associer une instance du handler au boutonMyHandler handler = new MyHandler();boutton.addClickHandler(handler);

Page 58: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

44 Chapitre 4. Widgets, panels, etc.

Toutes les méthodes des interfaces handlers reçoivent en paramètre une référencevers l’événement à l’origine de leur invocation. Cet objet (GwtEvent) contient enparticulier la source de l’événement, c’est-à-dire le widget d’origine (dans notre cas lebouton) ; ceci permet de partager un handler entre plusieurs widgets, le handler pouvantadopter un comportement différent en fonction de la source.

La documentation (Javadoc) de chaque widget spécifie précisément quels événe-ments sont susceptibles d’être générés par celui-ci.

4.2.2 Widgets simples

GWT propose une gamme de widgets suffisante pour construire une applicationcomplète et riche. Cependant, si vos besoins vous orientent vers des composantsplus complets ou spécialisés, GWT laisse la possibilité aux développeurs de créer deswidgets personnalisés de façon très simple (voir le chapitre 10) ; vous pourrez alorsvous tourner vers une des bibliothèques de composants disponibles, ou vous attelervous-même à la création de widgets.

Nous allons présenter dans un premier temps la gamme de widgets simples (c’est-à-dire non composites) de GWT.

Button

Un Button est un bouton simple qui déclenche une action lorsque l’utilisateur lepresse. Son label est défini par un fragment de HTML, ce qui permet d’y mettre autrechose qu’un simple texte.

Figure 4.1 — Widget Button (actif, inactif)

L’action à effectuer lors du clic est fournie au bouton sous forme d’une instance deClickHandler, de la façon suivante :

final Button button = new Button("Clic !");

// Handler pour le boutonclass MyHandler implements ClickHandler {

public void onClick(ClickEvent event) {Window.alert("onClick()");

}}

// Associer le handler au boutonMyHandler handler = new MyHandler();button.addClickHandler(handler);

Page 59: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 45

De façon plus compacte, si le handler n’est pas utilisé par d’autres widgets, on peututiliser une classe imbriquée (inner class) anonyme, comme ceci :

final Button button = new Button("Clic !");

button.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {Window.alert("onClick()");

}

});

Voire même passer le handler directement au constructeur du Button :

final Button button = new Button("Clic !", new ClickHandler() {

public void onClick(ClickEvent event) {Window.alert("onClick()");

}

});

PushButton

Un PushButton est un bouton graphique qui donne le contrôle total sur son apparenceau travers de différents styles CSS, selon son état.

Tableau 4.1 — Styles standards référencés par le PushButton

Style CSS État du PushButton.gwt-PushButton-up Non enfoncé, pointeur en dehors

.gwt-PushButton-down Enfoncé, pointeur en dehors

.gwt-PushButton-up-hovering Non enfoncé, pointeur au­dessus

.gwt-PushButton-up-disabled Non enfoncé, désactivé (disabled)

.gwt-PushButton-down-hovering Enfoncé, pointeur au­dessus

.gwt-PushButton-down-disabled Enfoncé, désactivé (disabled)

Différents constructeurs permettent de créer un PushButton avec des imagespersonnalisées différentes associées aux états enfoncé (up) et non enfoncé (down).

De même que pour Button, on peut associer à un PushButton un ClickHandler quisera invoqué lorsque l’utilisateur clique sur le bouton.

RadioButton

Un RadioButton est un genre de case à cocher (CheckBox) dont la particularité estqu’un au plus parmi un groupe peut être coché à un instant t. La sélection d’unRadioButton provoque la désélection de tous les autres du groupe.

Le groupe auquel appartient un RadioButton est désigné par une chaîne decaractères passée à son constructeur. Attention, si le label contient du code HTML, ilfaudra utiliser le constructeur prenant un booléen pour l’indiquer.

Page 60: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

46 Chapitre 4. Widgets, panels, etc.

Par exemple :

// Créer des RadioButtons dans le groupe "rbGroup0"RadioButton rb0 = new RadioButton("rbGroup0", "premier");RadioButton rb1 = new RadioButton("rbGroup0", "deuxi&egrave;me", true);RadioButton rb2 = new RadioButton("rbGroup0", "troisi&egrave;me", true);

// sélectionner le troisièmerb2.setValue(true);

// Les ajouter dans un PanelFlowPanel panel = new FlowPanel();panel.add(rb0);panel.add(rb1);panel.add(rb2);RootPanel.get("contenu").add(panel);

Figure 4.2 — Un groupe de trois widgets RadioButton

Caractères accentués

Si vous n’utilisez pas l’encodage HTML, vous pouvez toutefois inclure des caractèresaccentués dans les labels à condition que vos fichiers source soient encodés en UTF­8.Ce réglage se fait en principe dans les préférences de l’IDE, par exemple dans Eclipseon le trouve dans General > Workspace sous l’intitulé « Text file encoding ».

CheckBox

Une CheckBox est une simple case à cocher, pouvant prendre deux états : cochéou non coché. Elle possède également un label, et peut déclencher un événementValueChanged lorsque sa valeur (sélectionnée ou pas) change.

//Créer la checkboxfinal CheckBox checkBox = new CheckBox("cochez-moi !");

// Attacher un handler sur l’événement "ValueChanged"checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {

public void onValueChange(ValueChangeEvent<Boolean> event) {checkBox.setText(event.getValue() ? "décochez-moi..." :

"cochez-moi !");}

});

RootPanel.get("contenu").add(checkBox);

Figure 4.3 — Un widget CheckBox

Page 61: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 47

DatePicker

DatePicker est un widget qui permet de sélectionner une date de façon interactivegrâce à un calendrier. Le calendrier présente une vue d’un mois complet, et on peutse déplacer d’un mois en avant ou en arrière. Malheureusement, l’implémentation debase ne permet pas de sauter facilement à un mois ou une année donnée.

Bien évidemment, une valeur de type Date est associée à ce widget. Lorsque leDatePicker est instancié, il affiche la date correspondant à cette valeur ; un clic sur lacase d’un jour positionne la valeur à ce jour.

// créer un label (sans texte encore)final Label dateLabel = new Label();final DateTimeFormat dateFormat = DateTimeFormat.getFormat("dd/MM/yyyy");

// créer le DatePickerDatePicker datePicker = new DatePicker();datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {

public void onValueChange(ValueChangeEvent<Date> event) {// positionne le texte du label avec la date sélectionnée

Date selection = event.getValue();dateLabel.setText(dateFormat.format(selection));

};});

// positionner la date actuelleDate now = new Date();datePicker.setValue(now, true); // true pour déclencher ValueChangedHandler

RootPanel.get("contenu").add(datePicker);RootPanel.get("contenu").add(dateLabel);

Figure 4.4 — Widget DatePicker

Dans la figure 4.4 illustrant le widget DatePicker, on remarque que la valeur initialede la date reste visible (case encadrée).

Page 62: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

48 Chapitre 4. Widgets, panels, etc.

ToggleButton

Un ToggleButton est un bouton à deux états (non enfoncé, enfoncé). Contrairementà un PushButton, sa raison d’être n’est pas de déclencher une action, mais debasculer entre deux états ; de ce point de vue, il est fonctionnellement équivalentà une CheckBox.

En revanche, il est similaire au PushButton en ce sens qu’il est destiné à être styléau travers de styles CSS. Les deux widgets héritent de la classe abstraite CustomButton

dans laquelle sont définies les variantes de styles CSS appliqués selon l’état du bouton.

Tableau 4.2 — Styles référencés par le ToggleButton

Style CSS État du ToggleButton.gwt-ToggleButton-up Non enfoncé, pointeur en dehors

.gwt-ToggleButton-down Enfoncé, pointeur en dehors

.gwt-ToggleButton-up-hovering Non enfoncé, pointeur au­dessus

.gwt-ToggleButton-up-disabled Non enfoncé, désactivé (disabled)

.gwt-ToggleButton-down-hovering Enfoncé, pointeur au­dessus

.gwt-ToggleButton-down-disabled Enfoncé, désactivé (disabled)

Exemple :

// créer un labelfinal Label toggleLabel = new Label();

// créer le ToggleButtonfinal ToggleButton toggleButton = new ToggleButton("NON", "OUI");

toggleButton.addClickHandler(new ClickHandler() {public void onClick(ClickEvent event) {

// en cas de clic, positionner le texte du label// selon l’état du ToggleButtonif (toggleButton.isDown()) {

toggleLabel.setText("Je suis enfoncé !");}else {

toggleLabel.setText("Je ne suis pas enfoncé !");}

}});

// ajouter au PanelRootPanel.get("contenu").add(toggleButton);RootPanel.get("contenu").add(toggleLabel);

Figure 4.5 — Widget ToggleButton (état non enfoncé, état enfoncé)

Page 63: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 49

TextBox

TextBox est un champ de saisie textuelle classique, qui permet d’entrer du texte surune ligne (voir TextArea pour une saisie multilignes).

TextBox génère de nombreux événements, en particulier ceux liées à la saisie detexte (KeyUpEvent, KeyDownEvent, KeyPressEvent). Il est possible de lui associer unelongueur maximale (de texte autorisé) et un nombre de caractères visibles.

Voici un petit exemple qui associe à une TextBox un compteur qui affiche enpermanence le nombre de caractères tapés dans la TextBox :

// Créer la TextBoxfinal TextBox textBox = new TextBox();textBox.setMaxLength(20); // pas plus de 20 caractères saisistextBox.setVisibleLength(10); // pas plus de 10 caractères affichés à la fois

// Label qui servira de compteurfinal Label compteurLabel = new Label();

textBox.addKeyUpHandler(new KeyUpHandler() {public void onKeyUp(KeyUpEvent event) {

// positionne le label en fonction de la longueur du texte entréString text = textBox.getText();compteurLabel.setText("" + text.length()+ " caractère(s)");

}});

// ajouter au PanelRootPanel.get("contenu").add(textBox);RootPanel.get("contenu").add(compteurLabel);

Figure 4.6 — Widget TextBox (avec un compteur de caractères)

PasswordTextBox

Un PasswordTextBox est simplement une TextBox dont les caractères tapés parl’utilisateur sont masqués à l’écran. Pour le reste, tout est identique.

Figure 4.7 — Widget PasswordTextBox (avec un compteur de caractères)

Page 64: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

50 Chapitre 4. Widgets, panels, etc.

TextArea

TextArea est une zone de saisie de texte similaire à TextBox, à cette différence prèsqu’elle peut s’étendre sur plusieurs lignes. On peut en définir la largeur en termes denombre de caractères (sur base d’une valeur moyenne), et un nombre de lignes visibles.

// Créer la TextAreafinal TextArea textArea = new TextArea();textArea.setCharacterWidth(40); // largeur approx 40 caractèrestextArea.setVisibleLines(5); // 5 lignes visibles

// Label qui servira de compteur de voyelles/consonnesfinal Label compteur2Label = new Label();

textArea.addKeyUpHandler(new KeyUpHandler() {public void onKeyUp(KeyUpEvent event) {

// positionne le label en fonction du nombre de consonnes et voyellesString text = textArea.getText();int cons = 0;int voy = 0;for (int i = 0; i < text.length(); i++) {

char c = text.charAt(i);if ("aeiou".indexOf(c) >= 0) {

voy++;} else if ("bcdfghjklmnpqrstvwxyz".indexOf(c) >= 0) {

cons++;}

}compteur2Label.setText("" + voy + " voyelles, " + cons + " consonnes");}

});

// ajouter au PanelRootPanel.get("contenu").add(textArea);RootPanel.get("contenu").add(compteur2Label);

Figure 4.8 — Widget TextArea (avec un compteur de consonnes/voyelles)

Page 65: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 51

Hyperlink

Hyperlink est un hyperlien qui fonctionne en conjonction avec le système de gestiond’historique de GWT (lire à ce sujet le chapitre 8).

Attention, il ne s’agit pas d’un hyperlien générique ! Si on souhaite créer unhyperlien générique, on utilisera simplement le widget HTML comme ceci :

HTML hyperlink = new HTML("<a href=’http://code.google.com/webtoolkit’>" +"Google WebToolkit" +"</a>");

ListBox

ListBox présente une liste de choix à l’utilisateur, qui peut se présenter soit commeun widget intégré à son conteneur, soit dans un popup affiché à la demande.

À chaque élément de la liste est associé, en plus du label qui est affiché, une valeurqui est cachée. La valeur peut par exemple contenir un code ou un identifiant quin’est pas destiné à être affiché.

ListBox autorise la sélection simple (un seul élément sélectionné à la fois)ou multiple (plusieurs éléments sélectionnables). En mode de sélection multiple,l’utilisateur peut sélectionner ou désélectionner un élément individuel en cliquantsur celui-ci en combinaison avec la touche habituelle de sa plate-forme (Ctrl pourWindows et Linux, Cmd pour Mac OS).

Tableau 4.3 — Différentes utilisations du widget ListBox

Sélection simple Sélection multiple

Instanciation new ListBox();

ounew ListBox(false);

new ListBox(true);

Récupérationde la sélection

courante

getSelectedIndex() isItemSelected(i)

Positionnementde la sélection

courante

setSelectedIndex(i) setItemSelected(i,selected)

Page 66: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

52 Chapitre 4. Widgets, panels, etc.

Exemple :

// Création de la ListBoxfinal ListBox listBox = new ListBox(true);

// ajout des éléments et codes associéslistBox.addItem("lundi", "lun");listBox.addItem("mardi", "mar");listBox.addItem("mercredi", "mer");listBox.addItem("jeudi", "jeu");listBox.addItem("vendredi", "ven");listBox.addItem("samedi", "sam");listBox.addItem("dimanche", "dim");

// Label qui servira de résuméfinal Label resumeLabel = new Label();

// handler sur le changement de sélection de la ListBoxlistBox.addChangeHandler(new ChangeHandler() {

public void onChange(ChangeEvent event) {// concatène simplement les codes des éléments sélectionnésStringBuffer buf = new StringBuffer();for (int i = 0; i < listBox.getItemCount(); i++) {

if (listBox.isItemSelected(i)) {buf.append(listBox.getValue(i) + " ");

}}resumeLabel.setText(buf.toString());

}});

// ajouter au PanelRootPanel.get("contenu").add(listBox);RootPanel.get("contenu").add(resumeLabel);

Figure 4.9 — Une ListBox avec les jours de la semaine

Page 67: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 53

MenuBar

MenuBar est le widget de base qui sert à la construction des menus. Un MenuBar :

• peut être horizontal ou vertical ;• contient une liste d’éléments, chaque élément étant associé :

– soit à un objet de type Command (exécution d’une action),

– soit à un autre MenuBar (ouverture d’un sous-menu en popup).

De nombreux styles CSS sont associés au MenuBar et permettent de contrôler sonapparence.

Tableau 4.4 — Styles référencés par le MenuBar

Style CSS Élément concerné.gwt-MenuBar La barre de menu proprement dite

.gwt-MenuBar-horizontal Style appliqué aux barres de menuhorizontales

.gwt-MenuBar-vertical Style appliqué aux barres de menuverticales

.gwt-MenuBar .gwt-MenuItem Élément de menu

.gwt-MenuBar .gwt-MenuItem-selected Élément de menu sélectionné

.gwt-MenuBar .gwt-MenuItemSeparator Séparateurs entre les éléments de menu

.gwt-MenuBar .gwt-MenuItemSeparator

.menuSeparatorInnerComposant intérieur du séparateur

.gwt-MenuBarPopup .menuPopup{Top|Middle|Bottom}{Left|LeftInner|Center|CenterInner|Right|RightInner}

Composants des cellules des menuspopups ; respectivement :– haut, milieu, bas– gauche, gauche (intérieur), centre, centre(intérieur), droite, droite (intérieur)

Tree

Tree représente une arborescence de widgets que l’on peut développer, réduire etsélectionner.

Chaque nœud de l’arbre est constitué par une instance de TreeItem, qui :

• peut contenir un simple label textuel ou un widget quelconque ;• peut avoir un nombre quelconque d’enfants (eux-mêmes des TreeItem).

Page 68: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

54 Chapitre 4. Widgets, panels, etc.

On peut combiner texte et widgets dans un Tree à volonté, comme le montrel’exemple suivant :

TreeItem racine = new TreeItem("Noeud Racine");

TreeItem noeud1 = new TreeItem("Elements Texte");noeud1.addItem("Noeud textuel");noeud1.addItem("<b>HTML pour la mise en forme</b>");racine.addItem(noeud1);

TreeItem noeud2 = new TreeItem("Widgets");noeud2.addItem(new CheckBox("Case à cocher"));HorizontalPanel panelNode = new HorizontalPanel();panelNode.add(new Label("Et même une TextBox: "));panelNode.add(new TextBox());noeud2.addItem(panelNode);

racine.addItem(noeud2);

Tree tree = new Tree();tree.addItem(racine);

panel.add(tree);

Figure 4.10 — Une arborescence de widgets

SuggestBox

SuggestBox est une TextBox complétée d’un mécanisme qui fait apparaître dessuggestions au fur et à mesure que l’utilisateur introduit le texte. Si une suggestioncorrespond à ce que souhaite l’utilisateur, il peut alors la sélectionner et ainsi abrégersa frappe.

Chaque SuggestBox fonctionne en collaboration avec un SuggestOracle

qui est responsable de fournir les suggestions en fonction du texte déjà saisi. Pardéfaut, SuggestBox utilise MultiWordSuggestOracle qui tire ses propositions d’uneliste statique ; cependant, il est tout à fait possible d’écrire un SuggestOracle

qui interroge un serveur au moyen de RPC ou une autre méthode (voir chapitre 5)pour construire sa liste de propositions.

Pour implémenter un SuggestOracle, il suffit d’étendre la classe abstraiteSuggestOracle et d’implémenter la méthode abstraite :

public void requestSuggestions(Request request, Callback callback)

Page 69: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 55

Cette méthode sera appelée par la SuggestBox lorsqu’elle souhaitera obtenir uneliste de suggestions. Dans le profil de cette méthode, Request est une inner class deSuggestOracle qui contient les données de la requête, en particulier le texte saisi, etCallback est une interface définie également dans SuggestBox, dont il faudra appelerla méthode :

void onSuggestionsReady(Request request, Response response)

lorsque des suggestions seront prêtes.

La Response passée au callback sert essentiellement à encapsuler une liste desuggestions sous la forme d’objets implémentant l’interface Suggestion. Cette dernièreinterface expose deux méthodes :

String getDisplayString();

ou

String getReplacementString();

La première fournit la chaîne qui sera affichée par la SuggestBox dans la liste dechoix proposés, la seconde fournit la chaîne qui sera effectivement utilisée pour leremplacement.

À titre d’exemple, on va implémenter un SuggestOracle qui propose de capitaliserle texte saisi, c’est-à-dire de passer tout en majuscules ou minuscules. Pour commenceril faut définir une implémentation de Suggestion afin de pouvoir retourner lespropositions à la SuggestBox. Il s’agit d’une simple classe non mutable qui encapsuleles deux informations (replacementString et displayString) :

class SimpleSuggestion implements Suggestion {private final String replacementString;private final String displayString;

public SimpleSuggestion(String replacementString,String displayString) {

this.replacementString = replacementString;this.displayString = displayString;

}

public SimpleSuggestion(String replacementString) {this(replacementString, replacementString);

}

public String getReplacementString() {return replacementString;

}

public String getDisplayString() {return displayString;

}}

Page 70: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

56 Chapitre 4. Widgets, panels, etc.

On peut maintenant définir le SuggestOracle :

// Un SuggestOracle qui offre toujours deux propositions:// une correspondant au texte saisi passé en minuscules, l’autre// en majuscules.class CapsOracle extends SuggestOracle {

@Overridepublic void requestSuggestions(Request request, Callback callback) {

String query = request.getQuery();Suggestion s0 = new SimpleSuggestion(query.toUpperCase());Suggestion s1 = new SimpleSuggestion(query.toLowerCase());Response response = new Response(Arrays.asList(s0, s1));callback.onSuggestionsReady(request, response);

}}

Pour utiliser ce SuggestOracle, il suffit de le passer au constructeur de SuggestBox :

SuggestBox suggestBox = new SuggestBox(new CapsOracle());

Figure 4.11 — La SuggestBox avant sélection

Figure 4.12 — La SuggestBox après sélection

On peut également réagir à la sélection d’une proposition de l’oracle en attachantun SelectionHandler à la SuggestBox. Les événements générés sont de type Selectio-

nEvent<Suggestion> :

suggestBox.addSelectionHandler(new SelectionHandler<Suggestion>() {public void onSelection(SelectionEvent<Suggestion> event) {

GWT.log("Suggestion choisie: "+ event.getSelectedItem().getDisplayString(), null);

}});

Ceci peut s’avérer utile lorsqu’on souhaite effectuer des actions supplémentaires(autres que simplement remplacer le texte), ou bien récupérer des informationssupplémentaires contenues dans l’objet Suggestion.

La SuggestBox et son menu popup associé sont personnalisables au moyen de stylesCSS.

Page 71: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 57

Tableau 4.5 — Styles référencés par la SuggestBox

Style CSS Élément concerné.gwt-SuggestBox La TextBox proprement dite

.gwt-SuggestBoxPopup Le menu popup de choix

.gwt-SuggestBoxPopup .item Une suggestion

.gwt-SuggestBoxPopup .item-selected Une suggestion sélectionnée

.gwt-SuggestBoxPopup .suggestPopup{Top|Middle|Bottom}{Left|LeftInner|Center|CenterInner|Right|RightInner}

Composants des cellules du menu popup ;respectivement :– haut, milieu, bas– gauche, gauche (intérieur), centre, centre(intérieur), droite, droite (intérieur)

RichTextArea

Une RichTextArea est un éditeur de texte qui autorise l’utilisateur à entrer du textemis en forme (gras, italique, etc.). Le contenu est récupérable et positionnable sousforme de code HTML. Ce composant est souvent utilisé pour saisir du texte destiné àêtre publié ou en général lu par des humains.

Attention car le support de ce composant est fortement dépendant du navigateurcible... Son implémentation peut donc varier d’un navigateur à l’autre.

Contrairement à ce qu’on pourrait imaginer, ce composant ne contient pas debarre d’outils ni aucun contrôle permettant à l’utilisateur d’effectuer le formatage ;c’est entièrement au programmeur de fournir ce genre de contrôle. Pour interagir avecle contenu de la RichTextArea, les contrôles peuvent utiliser l’une ou l’autre des classessuivantes :

• BasicFormatter fournit des fonctions de formatage de base (gras, italique,souligné, etc.) ;

• ExtendedFormatter étend BasicFormatter en y ajoutant des fonctions plusavancées (liens, images, listes, etc.).

Les références vers les instances de ces formateurs s’obtiennent via les méthodesRichTextArea.getBasicFormatter() et RichtextArea.getExtendedFormatter().Attention toutefois car, selon le navigateur, ces méthodes peuvent retourner null sile formateur demandé n’est pas disponible sur la plate-forme de l’utilisateur !

Dans l’exemple suivant, on instancie une RichTextArea, et on y ajoute deuxboutons, un bouton Gras qui fait appel à la méthode toggleBold() du BasicFormatter

pour passer en gras la sélection courante, et un bouton Barré qui fait appel à la méthodetoggleStrikeThrough() pour barrer la sélection courante. À noter qu’on n’instanciechacun de ces boutons que si le formateur auquel il fait appel n’est pas null, ce quigarantit que la fonctionnalité correspondante est disponible.

Page 72: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

58 Chapitre 4. Widgets, panels, etc.

VerticalPanel vpanel = new VerticalPanel();vpanel.setSpacing(15);

HorizontalPanel buttonPanel = new HorizontalPanel();vpanel.add(buttonPanel);

RichTextArea area = new RichTextArea();vpanel.add(area);

final BasicFormatter basicFormatter = area.getBasicFormatter();if (basicFormatter != null) {

Button gras = new Button("Gras");buttonPanel.add(gras);gras.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {basicFormatter.toggleBold();

}});

}

final ExtendedFormatter extendedFormatter = area.getExtendedFormatter();if (extendedFormatter != null) {

Button barre = new Button("Barré");buttonPanel.add(barre);barre.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {extendedFormatter.toggleStrikethrough();

}});

}

RootPanel.get().add(vpanel);

Figure 4.13 — Widget RichTextArea (avec contrôles associés)

DialogBox

DialogBox est une classe de base pour créer des fenêtres de dialogue. Elle possède untitre et peut être déplacée par l’utilisateur. Son contenu est un widget qu’on lui passeravia setWidget(), après quoi on pourra appeler la méthode show() pour afficher ledialogue.

Un DialogBox peut optionnellement être modal, c’est-à-dire bloquer toute inter-action avec des widgets autres que lui-même tant qu’il est affiché. Il peut égalementêtre en auto hide, c’est-à-dire se masquer automatiquement si on clique en dehors. Cespropriétés sont spécifiées lors de l’instanciation du DialogBox.

Page 73: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 59

Si on veut construire un dialogue complet sur base de DialogBox, on pourraprocéder comme suit :

/*** DialogBox contenant un TextBox et un bouton OK.*/class InputDialog extends DialogBox {

/*** Créer le dialogue* @param title le titre*/public InputDialog(String title) {

super(false, true); // autohide désactivé, modal activésetText(title);// panel qui sera le contenu du widgetVerticalPanel panel = new VerticalPanel();panel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);// ajout de la TextBoxpanel.add(new TextBox());// ajout du bouton OKButton okButton = new Button("OK");okButton.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {// un clic sur le bouton OK masque le dialoguehide();

}});panel.add(okButton);// spécifier le panel comme contenu du dialoguesetWidget(panel);

}}

Le nouveau dialogue s’utilise alors de la façon suivante :

Button showDialogButton = new Button("afficher DialogBox");showDialogButton.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {new InputDialog("Votre nom ?").show();

}});

panel.add(showDialogButton);

Figure 4.14 — Une boîte de dialogue simple

Page 74: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

60 Chapitre 4. Widgets, panels, etc.

On peut remarquer au passage qu’au lieu d’utiliser DialogBox directement, onl’a sous-classé pour en faire InputDialog ; ce faisant on a naturellement et presquesans s’en rendre compte créé un nouveau widget GWT ! L’héritage est une desméthodes possibles pour créer son propre widget, vous pourrez en savoir davantage auchapitre 10.

4.2.3 Panels

Les panels sont des widgets un peu spéciaux, qui ont la caractéristique de pouvoircontenir d’autres widgets. Tous les panels exposent une méthode add(Widget) quipermet l’ajout d’un widget au panel, et remove(Widget) qui permet de retirer unwidget du panel.

En outre, la plupart des panels génériques offrent aussi des méthodes permettantd’accéder aux widgets-fils :

• getWidgetCount() retourne le nombre de widgets-fils ;• getWidget(int n) retourne le widget à l’index spécifié ;• iterator() retourne un itérateur pour parcourir les widgets-fils ;• remove(int n) permet de retirer un widget-fils désigné par son index.

Selon le cas, le panel peut aussi exposer des méthodes spécifiques, par exempleAbsolutePanel possède une méthode add(Widget, int, int) qui ajoute un widget-filsà une position absolue.

Il est important de comprendre qu’à chaque type de panel est associé un layout,c’est-à-dire une façon de disposer les widgets-fils à l’intérieur du panel. Par exemple,les widgets peuvent être simplement disposés l’un à droite du précédent (Horizontal-Panel), l’un par-dessus l’autre (DeckPanel), dans des cellules individuelles (HTMLTable),etc.

RootPanel

RootPanel est un panel particulier puisqu’il représente le « point d’attache » d’unearborescence de widgets GWT dans la page HTML hôte. Un RootPanel n’est jamaiscréé explicitement par l’application GWT, mais il est obtenu :

• soit via la méthode RootPanel.get(String id), qui retourne un RootPanelattaché à l’élément HTML possédant l’id spécifié dans la page HTML hôte ;

• soit via la méthode RootPanel.get(), qui retourne un RootPanel par défautattaché à l’élément BODY de la page hôte. Cette méthode fonctionne toujoursmême si aucun id n’est défini dans la page.

Si l’on veut qu’ils soient visibles, les widgets créés par l’utilisateur devrontobligatoirement, directement ou indirectement, être attachés à un RootPanel.

Page 75: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 61

AbsolutePanel

Un AbsolutePanel est un panel qui positionne ses fils via des coordonnées absolues.La superposition totale ou partielle de widgets est permise.

Exemple :

AbsolutePanel panel = new AbsolutePanel();panel.setPixelSize(200, 200);Button b1 = new Button("Bouton 1");panel.add(b1, 50, 50);Button b2 = new Button("Bouton 2");panel.add(b2, 70, 65);

Figure 4.15 — AbsolutePanel avec deux boutons qui se superposent

PopupPanel

Un PopupPanel est un panel destiné à être affiché sous forme de popup, c’est-à-direpar-dessus les autres widgets de l’application. À cet effet, il ne doit pas être ajouté à unautre panel, mais doit être affiché/masqué au moyen des méthodes show() et hide().

PopupPanel est une sous-classe de SimplePanel, c’est-à-dire un panel qui n’acceptequ’un seul widget-fils ; par conséquent, pour construire un PopupPanel complexe,il faudra l’encapsuler dans un panel approprié, et ce dernier sera déclaré commewidget-fils du PopupPanel. À noter que le fait d’appeler une seconde fois la méthodeadd() sur un SimplePanel se traduit par une IllegalStateException.

L’exemple suivant illustre une utilisation possible de PopupPanel pour implémenterun embryon d’infobulle (tooltip) : on crée un bouton, et on y associe un MouseOve-

rHandler qui affiche un PopupPanel (supposé contenir un message d’aide) à la positionde la souris.

final Button bouton = new Button("Bouton");final PopupPanel popup = new PopupPanel(true);Label label = new Label("Ceci est un bouton.");popup.add(label);bouton.addMouseOverHandler(new MouseOverHandler() {

public void onMouseOver(MouseOverEvent event) {// le pointeur de la souris survole le bouton:// afficher le popuppopup.setPopupPosition(event.getClientX(), event.getClientY());popup.show();// ajout d’un Timer pour faire disparaitre le popup après 2 sTimer timer = new Timer() {

@Overridepublic void run() {

popup.hide();}

Page 76: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

62 Chapitre 4. Widgets, panels, etc.

};timer.schedule(2000);

}});panel.add(bouton);

Notez l’utilisation d’un Timer pour faire disparaître automatiquement le PopupPa-nel après un délai si l’utilisateur ne clique pas en dehors.

Figure 4.16 — PopupPanel utilisé comme tooltip

StackPanel

Un StackPanel gère un ensemble de widgets-fils empilés verticalement, de sorte queseul l’un d’entre eux soit visible à un instant donné. Chaque widget est précédéd’un en-tête, et le fait de double-cliquer sur un en-tête va développer le widget-filscorrespondant, et réduire celui qui était précédemment développé s’il y en avait un.Ce genre de dispositif est parfois appelé accordéon (accordion) dans d’autres toolkits.

Figure 4.17 — StackPanel avec trois éléments

HorizontalPanel et VerticalPanel

HorizontalPanel et VerticalPanel sont deux panels qui positionnent leurs widgets-filsl’un à côté de l’autre, respectivement horizontalement et verticalement.

Les widgets-fils sont placés dans des cellules rectangulaires :

• la taille des cellules peut se régler via les méthodes setCellWidth() et setCell-Height() ;

• chaque widget peut être aligné indépendamment à l’intérieur de sa cellule via lesméthodes setCellHorizontalAlignement() et setCellVerticalAlignment().

En outre, on peut spécifier l’espacement entre deux cellules voisines via setSpa-cing(), et la largeur de la bordure avec setBorderWidth().

Page 77: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 63

Figure 4.18 — HorizontalPanel avec spacing=15

Figure 4.19 — VerticalPanel avec spacing=15

FlowPanel

FlowPanel est un panel qui n’ajoute aucune contrainte sur ses fils ; le résultat est doncmis en page comme le seraient des éléments HTML consécutifs. En général, le résultatest que les widgets-fils sont positionnés l’un à côté de l’autre horizontalement, avecun retour à la ligne en cas de débordement.

Figure 4.20 — FlowPanel

DeckPanel

DeckPanel positionne tous ses widgets-fils l’un sur l’autre comme une pile de cartes, desorte que seulement l’un d’entre eux (le sommet de la pile) soit visible à un momentdonné. Les lecteurs qui ont pratiqué Swing reconnaîtront l’équivalent du CardLayout.

Utilisation :

• les widgets-fils sont ajoutés normalement via la méthode add(Widget) ouinsert(Widget, int) ;

• le widget à placer en premier plan est désigné par la méthode showWidget(int).

À noter que ce panel sert de base au TabPanel (voir plus loin) dans lequel lasélection du widget actif se fait via des onglets placés au nord.

Page 78: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

64 Chapitre 4. Widgets, panels, etc.

VerticalSplitPanel et HorizontalSplitPanel

VerticalSplitPanel et HorizontalSplitPanel sont des panels qui acceptent unique-ment deux widgets-fils et les placent respectivement l’un au-dessus de l’autre et l’un àcôté de l’autre, en permettant à l’utilisateur d’ajuster l’espace alloué à l’un et l’autrewidget en déplaçant la barre qui les sépare. Au besoin, des ascenseurs seront ajoutés siun widget ne pouvait pas être contenu en totalité dans l’espace qui lui est alloué.

Utilisation :

• Pour un VerticalSplitPanel, on spécifie les widgets-fils avec setTopWidget() ousetBottomWidget(), et on y accède avec getTopWidget() ou getBottomWidget().

• Pour un HorizontalSplitPanel, on spécifie les widgets-fils avec setLeftWid-

get() ou setRightWidget(), et on y accède avec getLeftWidget() ou getRight-

Widget().• Dans les deux cas, on peut aussi utiliser la méthode add(Widget) commune

aux panels ; le premier appel positionnera le widget du haut (respectivementde gauche), le second du bas (respectivement de droite). Tout appel ultérieurrésultera en une IllegalStateException.

• La position du séparateur entre les deux widgets se règle avec setSplitPo-

sition(). Comme pour toutes les coordonnées, cette position s’indique enunités CSS ; dans le cas du séparateur, il peut être judicieux de l’indiqueren pourcentage, par exemple setSplitPosition("33%") donnera un tiers del’espace au premier composant.

Figure 4.21 — HorizontalSplitPanel séparant deux labels

Figure 4.22 — VerticalSplitPanel séparant deux labels

Page 79: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 65

Dockpanel

DockPanel est un panel à la fois puissant et complexe, et qui peut servir de base à desinterfaces riches ; les lecteurs qui ont pratiqué Swing reconnaîtront sans doute uneressemblance avec le fameux BorderLayout.

DockPanel divise son espace en cinq zones (nord, sud, est, ouest et centre), commele montre la figure 4.23.

Figure 4.23 — Les cinq zones de l’espace de DockPanel

L’ajout de widget-fils se fait grâce à la méthode add(Widget, DockLayoutConstant).Le second paramètre précise l’endroit où sera placé le widget ; les valeurs possiblessont :

• NORTH ou SOUTH : le composant sera placé au nord ou au sud ;• EAST ou WEST : le composant sera placé à l’est ou à l’ouest ;• LINE_START ou LINE_END sont des synonymes respectivement pour WEST et EAST

mais qui dépendent de la direction d’écriture. Dans les environnements oùl’écriture va de droite à gauche, la correspondance est inversée.

• CENTER : le composant sera placé au centre.

À l’exception du centre, il est possible d’ajouter plusieurs widgets dans une mêmezone ; les widgets seront arrangés de l’extérieur vers l’intérieur.

Figure 4.24 — DockPanel avec plusieurs éléments par zone

Comme HorizontalPanel et VerticalPanel, DockPanel est un CellPanel et arrangeses fils dans des cellules. Il est donc possible de la même manière de spécifierl’alignement des widgets à l’intérieur des cellules et l’espacement entre ces derniers.

Page 80: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

66 Chapitre 4. Widgets, panels, etc.

TabPanel

TabPanel est l’implémentation en GWT du classique sélecteur à onglets. Chaquewidget ajouté est associé à un onglet, et un clic sur un onglet fait passer au premierplan le widget associé.

L’ajout d’un widget se fait avec une des méthodes :

• add(Widget, String) ajoute un widget avec le texte spécifié dans l’onglet ;• add(Widget, String, boolean) ajoute un widget avec le texte spécifié dans

l’onglet, qui peut être du HTML si le booléen est true ;• add(Widget, Widget) permet de mettre un widget quelconque dans l’onglet à

la place d’un simple texte. Ceci permet de créer des onglets constitués d’uneimage par exemple.

Figure 4.25 — TabPanel

DisclosurePanel

DisclosurePanel qu’on pourrait traduire par « panneau escamotable » est un widgetcomposé d’un en-tête et d’un contenu ; le contenu peut se cacher ou s’afficher encliquant sur l’entête. En principe, ce dernier est précédé d’un petit triangle pointe àdroite pour indiquer l’existence d’un contenu non affiché, et pointe en bas lorsque cecontenu est affiché.

Utilisation :

• utiliser le constructeur DisclosurePanel(String) pour créer un en-tête textuel,ou DisclosurePanel(Widget) pour utiliser un widget comme en-tête ;

• utiliser add(Widget) ou setContent(Widget) pour spécifier le contenu du panel(c’est à dire la partie escamotable) ;

• utiliser setOpen(boolean) pour passer programmatiquement de l’état ouvert àfermé ou vice versa.

Grid et FlexTable

Les tableaux en GWT peuvent être manipulés via deux classes :

• Grid est une table rectangulaire qu’on doit dimensionner explicitement ;• FlexTable est une table qui s’agrandit automatiquement au fur et à mesure que

des cellules sont créées. La table n’est pas forcément rectangulaire (chaque lignepeut contenir un nombre différent de cellules), et des cellules peuvent êtrefusionnées.

Page 81: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 67

Figure 4.26 — DisclosurePanel (fermé, ouvert)

Toutes deux héritent de la classe abstraite HTMLTable, et partagent un certainnombre de caractéristiques ; en particulier, chaque cellule peut contenir du texte, duHTML, ou un widget quelconque.

L’utilisation de Grid est très simple :

• instancier Grid avec les dimensions initiales (lignes × colonnes) ;• positionner le contenu des cellules avec setText pour du texte simple, setHTML

pour du HTML ou setWidget pour insérer un widget. La cellule doit existerauparavant, faute de quoi une IndexOutOfBoundsException sera levée ;

• utiliser insertRow, removeRow, resizeColumns, resizeRows ou resize pour agirdynamiquement sur les dimensions de la table.

L’utilisation de FlexTable est légèrement différente :

• instancier FlexTable (le constructeur ne prend pas de paramètres) ;• positionner le contenu des cellules avec setText pour du texte simple, setHTML

pour du HTML ou setWidget pour insérer un widget. Si une cellule n’existe pas,la table sera étendue à la taille nécessaire ;

• utiliser getFlexCellFormatter().setColSpan ougetFlexCellFormatter().setRowSpan pour fusionner une cellule avec sesvoisines ;

• utiliser éventuellement insertRow, removeRow ou addCell pour agir dynamique-ment sur les dimensions de la table.

À titre d’exemple, nous allons créer une FlexTable avec une « cellule baladeuse »qu’on pourra déplacer dans les quatre directions au moyen de boutons ; au fur et àmesure qu’elle se déplacera vers la droite ou vers le bas, les cellules seront créées aubesoin.

Page 82: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

68 Chapitre 4. Widgets, panels, etc.

Tout d’abord, on définit une sous-classe de Button, dont l’appui appellera laméthode move (définie ultérieurement) en lui passant des valeurs fixées à la créationdu bouton, correspondant à un décalage vertical et horizontal.

// sous-classe de Button spécialisée qui fait appel à la méthode move// avec les paramètres passés à son constructeurclass DirButton extends Button{

public DirButton(String label, final int deltax, final int deltay) {super(label);addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {move(deltax, deltay);

}});

}}

La table est créée comme suit :

private FlexTable table;private VerticalPanel buttonPanel;private int row = 0;private int col = 0;

// créer la FlexTabletable = new FlexTable();table.setBorderWidth(1);table.setCellPadding(25);

La « cellule baladeuse » sera constituée d’un panel qui regroupera les quatreboutons directionnels :

// créer le groupe de boutons qui constituera la "cellule baladeuse"buttonPanel = new VerticalPanel();buttonPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);

buttonPanel.add(new DirButton("^", -1, 0));HorizontalPanel hPanel = new HorizontalPanel();hPanel.add(new DirButton("&lt;", 0, -1));hPanel.add(new DirButton("&gt;", 0, +1));buttonPanel.add(hPanel);buttonPanel.add(new DirButton("v", +1, 0));

On place le groupe de boutons à la position initiale, c’est à dire (0, 0) :

//positionner initialement le groupe de boutonstable.setWidget(row, col, buttonPanel);

// ajouter la tableRootPanel.get("contenu").add(table);

Page 83: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

4.2 Widgets et panels 69

Il reste à définir la méthode move qui sera appelée par les boutons directionnelslorsque ceux-ci seront pressés :

/*** Déplace le groupe de boutons* @param deltax décalage horizontal* @param deltay décalage vertical*/protected void move(int deltax, int deltay) {// retirer le groupe de boutons de la tabletable.remove(buttonPanel);

// calculer les nouvelles positionsrow += deltax;if (row < 0) {

row = 0;}col += deltay;if (col < 0) {

col = 0;}

// replacer le groupe de boutonstable.setWidget(row, col, buttonPanel);}

Et le résultat après avoir fait faire un peu de chemin à la cellule baladeuse(figure 4.27).

Figure 4.27 — La FlexTable et sa cellule baladeuse

Le listing complet de cet exemple est accessible en annexe 2.

Page 84: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 85: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Communiquer avec le serveur

5

ObjectifDans ce chapitre, nous allons détailler les principes et l’utilisation du mécanisme deRPC (Remote Procedure Call) de GWT, qui permet d’effectuer des appels à la partieserveur de l’application.

5.1 CODE CLIENT VS CODE SERVEUR

Une différence fondamentale entre les applications AJAX (GWT y compris) et lesapplications web traditionnelles est qu’à la différence de ces dernières, une applicationAJAX n’a besoin que de récupérer les données dont elle a besoin, pas de recharger latotalité de la page HTML.

Par cet aspect, une application développée avec GWT est essentiellement similaireà une application client-serveur traditionnelle, et de la même manière elle doit doncpartager les responsabilités entre le client et le serveur. Une partie du code résidedonc sur un serveur, et est invoquée par le client, par exemple lorsqu’il y a besoin derécupérer des données pour rafraichir une liste, etc.

Lorsque le code client GWT (c’est-à-dire le code qui s’exécute dans le navigateur)a besoin de communiquer avec le serveur, la manière la plus naturelle de le faire estd’utiliser le mécanisme de RPC (Remote Procedure Call, appel de procédure à distance)standard de GWT, sur lequel portera l’essentiel de ce chapitre. Cependant, ce n’estpas une obligation, et il est également possible d’appeler des services de nature diversecomme des web services ou des services encodant les données avec JSON.

Page 86: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

72 Chapitre 5. Communiquer avec le serveur

5.2 LES PRINCIPES DE GWT RPC

Le mécanisme de RPC promu par GWT s’appuie sur la norme Servlets Java, qui estle standard de fait pour l’implémentation de services distants en Java. Les servicesainsi implémentés peuvent donc être déployés sur tous les serveurs d’application Javaimplémentant la spécification « servlets », c’est-à-dire l’immense majorité d’entreeux : Tomcat, jetty, GlassFish, WebSphere, WebLogic, etc. En utilisant ce mécanismeRPC, on bénéficie également de l’optimisation du transport des objets sérialisés (viale compilateur GWT), ce qui n’est pas forcément le cas pour les autres mécanismes.

Il peut paraître inutile de le repréciser, mais le compilateur GWT ne convertitque le code « client » en JavaScript... GWT n’influe en rien sur votre capacitéà exécuter du bytecode natif dans une JVM standard côté serveur. En particulier,les limitations qui s’appliquent au code Java client n’ont pas cours pour le codeserveur ! Vous êtes libre d’employer toutes les bibliothèques Java et toutes lestechniques de programmation que vous souhaitez.

Un point important à avoir en tête lorsqu’on écrit du code client serveur avecGWT est la notion d’asynchronisme : tous les appels RPC sont forcément asynchrones.Qu’est-ce que cela signifie ? Concrètement, cela veut dire que lorsqu’on effectue unappel RPC, on récupère la main immédiatement, sans attendre la réponse du serveur.Lorsque la réponse arrive, une méthode désignée du client (appelée callback) estinvoquée, et celle-ci a accès aux résultats de l’appel. Il est de fait impossible de faireun appel RPC et de « bloquer » jusqu’à la réception de la réponse.

Ce choix se justifie par le caractère mono-thread de JavaScript ; en effet desopérations longues peuvent provoquer un blocage de l’application du point de vue del’utilisateur, voire même un blocage complet du navigateur. Pour éviter ce risque, lesconcepteurs de GWT ont purement et simplement banni les appels RPC synchrones.

Cela peut sembler extrêmement contraignant, mais en pratique il est toujourspossible de contourner cette limitation. Par exemple, si vous devez afficher les résultatsd’une recherche qui s’effectue côté serveur, au lieu de coder comme il serait plus naturelde le faire (et comme il est courant de procéder dans les clients lourds classiques) :

1. appeler le service de recherche ;

2. attendre le retour ;

3. afficher les résultats ;

le flux des traitements GWT sera plutôt :

1. appeler le service de recherche ;

2. (faire autre chose...) ;

3. lorsque les résultats arrivent, afficher les résultats.

La différence peut paraître minime, mais elle est essentielle : dans le deuxièmecas, l’utilisateur conserve la main et peut effectuer d’autres actions, alors que dans lepremier cas, il est bloqué tant que le serveur n’a pas répondu.

Page 87: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.2 Les principes de GWT RPC 73

Le caractère asynchrone impose tout de même une certaine prudence, puisquepar nature on ne sait pas exactement à quel moment la réponse va arriver, ni parconséquent quand le callback sera exécuté. Le traitement des erreurs peut s’avérer aussid’autant plus délicat.

5.2.1 Classes et interfaces mises en jeu

Chaque service RPC GWT est en réalité une petite famille de classes et interfacesqui ont chacune leur utilité. Heureusement, certaines sont générées dynamiquementau runtime par GWT, de sorte que l’on n’a pas besoin de s’en préoccuper. D’autrespeuvent être construites de façon mécanique à partir de l’interface propre du service,et d’ailleurs plusieurs plugins GWT s’en chargent automatiquement.

Voyons le diagramme des classes mises en jeu :

Figure 5.1 — Diagramme des classes mises en jeu

• YourService est l’interface qui contient les méthodes qui seront exposées parvotre service. C’est à vous de l’écrire ; il n’y a pas de contraintes sur ces méthodes,à part le fait que tous les objets passés en paramètre ou retournés par le servicedoivent être sérialisables au sens de GWT RPC. Cette notion est subtilement dif-férente de la notion habituelle de sérialisabilité de Java ; nous y reviendrons plusloin. Cette interface étend com.google.gwt.user.client.rpc.RemoteService,cette dernière étant une simple interface marqueur (sans méthodes).

• YourServiceImpl est l’implémentation de cette interface. Le code de cette classetournera côté serveur, il est donc possible d’utiliser toutes les techniques deprogrammation offertes par Java. Cette classe doit en outre étendre RemoteSer-

viceServlet.

Page 88: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

74 Chapitre 5. Communiquer avec le serveur

• YourServiceAsync est une interface dérivée mécaniquement de YourService,en transformant chaque méthode de la façon suivante :

– le type de retour original, s’il y en a un, est remplacé par void,– un paramètre est ajouté en fin de liste ; ce paramètre est de type AsyncCall-

back<T>, où T est le type de retour de la méthode originale. Si la méthoderetournait void, on utilisera AsyncCallback seul ou AsyncCallback<Void>.

Cette interface sera celle que vous manipulerez dans le code client.• Enfin, YourServiceProxy est une implémentation de YourServiceAsync (la

version asynchrone de votre interface de base). Cette classe est générée pourvous automatiquement par le compilateur GWT, de sorte que vous n’aurez pasà vous en préoccuper. Son rôle est de router les appels provenant du clientvers l’implémentation réelle du service, qui se trouve sur le serveur (classeYourServiceImpl). Elle prend en charge de façon totalement transparente toutela « mécanique » qui est impliquée par un appel RPC, notamment la créationde la requête, la sérialisation des paramètres, l’envoi de la requête, le traitementde la réponse, la désérialisation du résultat, et pour finir l’appel du callbackque vous lui avez passé. YourServiceProxy implémente également l’interfaceServiceDefTarget, qui permet de spécifier l’URL à utiliser pour communiqueravec le serveur.

Remarque à propos de YourServiceAsync

Si l’interface asynchrone ne correspond pas à l’interface de base moyennant lesrègles de transformation énoncées, une erreur sera émise par le hosted mode lors dulancement de l’application.

Une fois qu’on a bien compris le rôle de chacune de ces classes/interfaces, leurraison d’être devient évidente, de sorte que le diagramme initial n’est plus si complexe...Dans la suite, nous allons voir comment mettre en pratique cette théorie en voyantcomment implémenter un service RPC puis comment l’appeler depuis le client.

5.3 LA CRÉATION D’UN SERVICE PAS À PAS

5.3.1 Écriture des interfaces et de l’implémentation

La création d’un service implique les étapes suivantes :

1. Écrire l’interface de base du service (YourService). Cette interface est diteaussi « interface synchrone », par opposition à l’interface asynchrone. Cetteinterface doit étendre RemoteService.

2. Écrire l’implémentation de l’interface synchrone. Cette implémentation doitétendre RemoteServiceServlet.

3. Générer la version asynchrone de l’interface synchrone, comme décritplus haut. Il est toujours préférable de faire cela automatiquement si votreIDE le permet.

Page 89: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.3 La création d’un service pas à pas 75

À titre d’exemple, nous allons implémenter un service à haute valeur ajoutée :l’addition...

L’interface synchrone pourra ressembler à ce qui suit :

package oge.gwt.chap52.client;import com.google.gwt.user.client.rpc.RemoteService;import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

public interface AdditionService extends RemoteService {long additionner(long x, long y);

}

Rien de bien mystérieux ici, on déclare simplement que notre service va exposerune méthode « additionner » qui prend deux long en paramètre, et retourne un long.

L’implémentation du service sera simpliste car là n’est pas le propos, mais vousimaginez bien qu’on peut substituer ce traitement trivial par tout autre traitementcomplexe :

package oge.gwt.chap52.server;import oge.gwt.chap52.client.AdditionService;import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class AdditionServiceImpl extends RemoteServiceServlet implementsAdditionService {

public long additionner(long x, long y) {return x + y;

}}

Notez simplement que cette classe est déployée uniquement côté serveur, c’estpour cette raison qu’elle se trouve dans le sous-package server.

Enfin, l’interface asynchrone est directement déduite de l’interface synchrone ;comme on le voit, le type de retour est devenu void et un troisième paramètre s’estajouté pour permettre de passer un callback qui sera appelé lorsque le service auraretourné sa réponse :

package oge.gwt.chap52.client;import com.google.gwt.user.client.rpc.AsyncCallback;

public interface AdditionServiceAsync {void additionner(long x, long y, AsyncCallback<Long> callback);

}

Le type exact du callback est AsyncCallback<Long>, ce qui veut dire qu’on va passerau callback un objet de type Long. Notez bien que le callback est du domaine du client,l’implémentation du service n’a pas à s’en soucier.

Attention, cette interface asynchrone n’existe que pour permettre au clientd’appeler le service RPC, mais ce n’est pas à vous de fournir son implémentation :GWT la génèrera automatiquement pour vous.

Voilà, le service est défini ! Mais avant de pouvoir l’appeler il faut bien sûr ledéployer sur un serveur.

Page 90: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

76 Chapitre 5. Communiquer avec le serveur

5.3.2 Déploiement sur le serveur embarqué

Comme nous l’avons vu, l’implémentation du service, en plus d’implémenter l’inter-face synchrone, étend RemoteServiceServlet. En réalité chaque service GWT RPCest une servlet, et peut donc être déployé sur tout conteneur de servlets compatibleavec cette spécification. Attention, vous ne devez pas étendre HttpServlet comme sivous implémentiez une servlet complète ; GWT se chargera en effet de l’interprétationde la requête, de la désérialisation des paramètres, de l’appel à la méthode adéquate,de la construction de la réponse et de la sérialisation du paramètre de retour (le caséchéant).

Pour faciliter le test des services GWT RPC en phase de développement, le serveurdu hosted mode embarque une version de Jetty, un conteneur de servlets qui permet dedéployer très facilement des services GWT RPC localement. Pour déclarer un serviceGWT RPC dans le serveur embarqué, il suffit d’ajouter les lignes suivantes au fichierWEB-INF/web.xml qui doit se trouver dans le dossier war de votre projet :

<servlet><servlet-name>addServlet</servlet-name><servlet-class>oge.gwt.chap52.server.AdditionServiceImpl</servlet-class>

</servlet><servlet-mapping>

<servlet-name>addServlet</servlet-name><url-pattern>/gwtchap52/add</url-pattern>

</servlet-mapping>

Cela signifie en d’autres termes :

• on déclare une servlet nommée « addServlet » dont l’implémentation estfournie par la classe oge.gwt.chap52.server.AdditionServiceImpl ;

• cette servlet est associée à l’URL /gwtchap52/add.

On peut constater que cette méthode est strictement identique à la façon standardde déclarer une servlet, ce qui veut dire que le service pourra être déployé sur toutautre conteneur de servlets avec la même configuration.

Une note sur l’URL : la première partie (gwtchap52) doit correspondre au nomdu module GWT, ou bien à son alias si la fonction « rename-to » a été utilisée (voir§ 2.3.4 Le fichier module) ; quoiqu’il en soit, elle doit correspondre au sous-dossier dudossier war dans lequel se trouvent les fichiers, c’est-à-dire l’URL de base. La secondepartie est un nom arbitraire que vous donnez à votre service, et qui sera utilisé par leclient pour désigner le service à appeler.

Dernier point à vérifier : le fichier gwt-servlet.jar, qui contient le code de GWTdédié à la partie serveur du mécanisme RPC, doit se trouver dans war/WEB-INF/lib,et les classes Java compilées (notamment l’implémentation du service) doivent setrouver sous war/WEB-INF/classes. Encore une fois, ce ne sont là que les pratiquesstandards du déploiement d’applications web.

Page 91: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.3 La création d’un service pas à pas 77

5.3.3 La réalisation d’un appel RPC

Une fois la partie serveur en place, on peut enfin implémenter l’appel au service côtéclient.

Pour appeler un service GWT RPC, il faut obtenir une référence vers un objet quiimplémente l’interface asynchrone du service. Cette référence s’obtient de façon trèssimple en appelant la méthode suivante :

GWT.create(MyService.class)

Le résultat est un objet qui implémente MyServiceAsync (pour autant que celle-ciait été définie correctement). Grâce aux types génériques de Java 5, le résultat n’a pasbesoin d’être transtypé (cast) et on peut donc écrire :

MyServiceAsync service = GWT.create(MyService.class) ;

Une fois la référence obtenue, il faut indiquer l’URL cible du service, c’est-à-direl’URL sur laquelle est déployée la servlet qui implémente le service. Pour cela, il fautappeler la méthode ServiceDefTarget.setServiceEntryPoint(String url).

Cette méthode fait partie de l’interface ServiceDefTarget que l’instance obtenuede GWT.create() implémente également (en plus de l’interface asynchrone du service).Il suffit donc de caster cette référence vers ServiceDefTarget ; on pourra donc écrire :

((ServiceDefTarget) service).setServiceEntryPoint("/path.to.service");

Par exemple, pour accéder à notre service d’addition, en supposant qu’il a étédéployé sur /gwtchap52/add (voir url-pattern dans war/WEB-INF/web.xml), on écrira :

((ServiceDefTarget) service).setServiceEntryPoint("/gwtchap52/add");

Pour rendre cet appel indépendant de l’URL de base, on pourra écrire aussi :

((ServiceDefTarget) service). setServiceEntryPoint(GWT.getModuleBaseURL() + "add");

Enfin, une fois ceci fait, on peut procéder à l’appel, non sans avoir défini uncallback à appeler en cas de succès (ou d’échec) de l’appel. On peut écrire une classespécialisée pour implémenter ce callback, mais il est souvent plus aisé de l’écrire sousforme d’inner-classe anonyme.

Le callback doit obligatoirement implémenter deux méthodes :

• void onSuccess(T result) où T est le type de retour de la méthode synchronecorrespondante, méthode qui sera appelée en cas de succès, avec commeparamètre le résultat de l’appel ;

• void onFailure(Exception e), méthode qui sera appelée en cas d’échec, aveccomme paramètre l’exception traduisant la cause de l’échec.

Page 92: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

78 Chapitre 5. Communiquer avec le serveur

L’appel se fera donc comme suit :

service.myMethod(x, y, new AsyncCallback<Long>() {public void onFailure(Throwable caught) {// faire quelque chose en cas d’échec

}public void onSuccess(Long result) {

//faire quelque chose en cas de succès}});

Encore plus concis

Pour rendre le code client encore plus concis, on peut faire précéder la déclara­tion de l’interface synchrone du service par l’annotation @RemoteServiceRelative-

Path(relativeURL).Si cette annotation est présente, alors le proxy GWT effectuera automatiquementà votre place l’appel à setServiceEntryPoint en lui passant comme paramètreGWT.getModuleBaseURL() + relativeURL, où relativeURL est la valeur de l’uniqueparamètre de l’annotation.Par exemple, on pourra réécrire l’interface de notre service d’addition comme suit :@RemoteServiceRelativePath("add")

public interface AdditionService extends RemoteService {

long additionner(long x, long y);

}

Côté client, l’appel se résumera alors à obtenir une référence vers l’implémentationde l’interface asynchrone via GWT.create(), et appeler la méthode voulue de cetteinterface.

5.4 EXEMPLE COMPLET

Pour mettre en œuvre notre service d’addition, nous allons réaliser une interfacegraphique très simple qui permettra de saisir deux nombres ; un bouton déclencheral’appel à notre service d’addition et affichera le résultat. Le listing complet de l’exempleest accessible en annexe 3.

La déclaration du service sera identique à ce que nous avons défini plus haut.

L’interface synchrone :

package oge.gwt.chap52.client;import com.google.gwt.user.client.rpc.RemoteService;import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

public interface AdditionService extends RemoteService {long additionner(long x, long y);

}

Page 93: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.4 Exemple complet 79

L’interface asynchrone :

package oge.gwt.chap52.client;import com.google.gwt.user.client.rpc.AsyncCallback;

public interface AdditionServiceAsync {void additionner(long x, long y, AsyncCallback<Long> callback);

}

L’implémentation :

package oge.gwt.chap52.server;import oge.gwt.chap52.client.AdditionService;import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class AdditionServiceImpl extends RemoteServiceServlet implementsAdditionService {

public long additionner(long x, long y) {return x + y;

}}

Le fichier HTML sera simpliste puisque nous allons créer les éléments d’interface autravers du code GWT. On se contentera d’un élément <div> avec un ID « container »qui nous permettra de le référencer dans le code GWT.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html><head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script type="text/javascript" language="javascript"

src="gwtchap52/gwtchap52.nocache.js"></script>

</head>

<body><h1><p align="center">Exemple GWT-RPC</p></h1>

<div align="center" id="container"></div></body>

</html>

Après avoir vérifié que tout le code est correct (annexe 3), vous pouvez lancer letest en mode hôte avec le bouton Run as... > Web application. Après quelques instants,vous verrez la fenêtre « Google Web Toolkit Hosted Mode » s’ouvrir (figure 5.2) ; dansla console, vous noterez que la première ligne signale le démarrage du serveur Jettyembarqué. Par défaut, Jetty écoute sur le port 8080, mais c’est bien sûr paramétrable.

Page 94: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

80 Chapitre 5. Communiquer avec le serveur

Figure 5.2 — Console en mode hôte

La fenêtre de navigateur associée au mode hôte montre l’interface que nous avonsdéfinie (figure 5.3). Un petit clic sur le bouton = et on peut vérifier que l’appel auserveur fonctionne correctement (figure 5.4)...

Figure 5.3 — L’interface du service d’addition

Page 95: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.5 Utilisation d’un serveur externe 81

Figure 5.4 — Le résultat de l’addition...

5.5 UTILISATION D’UN SERVEUR EXTERNE

Le serveur embarqué n’est destiné qu’à tester plus facilement votre application GWTen phase de développement. Lorsque sera venu le temps de passer en environnementde production ou assimilé, il faudra alors la déployer sur un serveur web de production.Deux types de contenu sont à déployer : d’une part les pages statiques (on entendpar là les ressources dont le contenu n’est pas généré dynamiquement, mais issu d’unfichier ; ceci comprend donc les fichiers JavaScript issus de la compilation GWT)et d’autre part, le cas échéant, les servlets implémentant les services RPC auxquelsaccède le client.

Pour les fichiers statiques, tout serveur web fera l’affaire, cependant pour déployerles servlets, il faudra au minimum un conteneur (ou moteur) de servlets. De nombreuxserveurs web répondent à cette contrainte, commerciaux ou non, mais heureusement,grâce à la normalisation des API « servlets », la façon de déployer une applicationweb est relativement similaire pour tous, d’autant plus que depuis la version 1.6,l’organisation d’un projet GWT suit cette norme pour faciliter le travail de packaginget de déploiement.

En règle générale, le déploiement se résume à :

1. exécuter la compilation GWT de votre projet ;

2. créer un fichier .war qui reprend le contenu du dossier war de votre projet ;

3. déposer ce fichier dans un dossier spécifique du serveur web où il sera détectéet autodéployé (si le serveur est configuré dans ce sens), ou bien déployermanuellement le fichier .war.

En effet, si vous avez suivi les recommandations pour la structure de votre projet(voir § 2.3 Anatomie d’un projet GWT), le dossier war contient déjà tout ce qui estnécessaire au déploiement : fichiers statiques, web.xml, bibliothèques Java addition-nelles, et code Java serveur compilé ; ne manque que le résultat de la compilationGWT.

Page 96: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

82 Chapitre 5. Communiquer avec le serveur

Attention

Ne pas oublier d’inclure le fichier gwt-servlet.jar dans les bibliothèques additionnelles(WEB-INF/lib) si vous avez du code serveur !

Lorsque le déploiement est terminé, vous devriez pouvoir accéder à votre applica-tion à l’adresse http://serveur:8080/MonAppli/MonAppli.html, en supposant que leserveur écoute sur le port 8080.

Remarque

Les problèmes les plus courants qui peuvent survenir lors du déploiement d’uneapplication GWT sur un serveur sont des erreurs d’URL, par exemple si le clienttente d’accéder à un service sur une URL incorrecte. Pour résoudre ces erreurs,activez le journal des accès (access log) sur le serveur web et vérifiez l’URL appelée ;assurez­vous que la servlet est mappée sur la bonne URL dans le fichier web.xml

(élément <url-pattern>).

5.6 CONTRAINTES DE SÉRIALISATION

Dans l’exemple précédent, nous avons transmis au service distant deux paramètres detype long, et en retour le callback nous a transmis un résultat de type long. Bien sûr,GWT RPC n’est pas limité à ce type de paramètres, et on peut transmettre et recevoiren retour des instances de toutes sortes de classes, pour peu que celles-ci respectentquelques contraintes.

Pour transmettre les objets au travers de la connexion réseau entre le client GWTet le serveur, GWT s’appuie sur le concept de sérialisation. La sérialisation est ce quipermet de transformer l’état interne d’un objet en une série d’octets pour pouvoir soitle transmettre via un lien réseau (c’est notre cas), soit le stocker dans le but de le « res-susciter » plus tard. La sérialisation est un concept natif de Java, mais il convient d’êtreprudent car le concept de sérialisation de GWT diffère subtilement de celui de Java.

Un type est dit sérialisable au sens de GWT si une des conditions suivantes estvraie :

• il s’agit d’un type primitif, tel que char, byte, short, int, long, boolean, float,double ;

• il s’agit d’un « wrapper » d’un type primitif (Char, Byte, Integer, Long, Boolean,Float, Double) ;

• il s’agit d’une instance de String ou Date ;• il s’agit d’une énumération (attention toutefois, seul le nom de la constante est

sérialisé, pas les éventuelles valeurs des champs qu’elle peut contenir) ;• il s’agit d’un tableau (array) de types sérialisables ;• il s’agit d’un type dont il existe au moins une sous-classe sérialisable connue ;• il s’agit d’un type déclaré comme sérialisable par l’utilisateur.

Page 97: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.7 Les exceptions 83

5.6.1 Types sérialisables déclarés par l’utilisateur

En dehors des types sérialisables par GWT nativement, une classe quelconque estégalement sérialisable si toutes les conditions suivantes sont remplies :

• elle implémente com.google.gwt.user.client.rpc.IsSerializable oujava.io.Serializable, soit directement, soit au travers de l’héritage ;

• tous les champs non final et non transient sont eux-mêmes sérialisables ;• elle possède un constructeur sans argument (ou pas de constructeur).

Pourquoi IsSerializable ?

L’existence de l’interface IsSerializable s’explique pour des raisons historiques :dans les premières versions de GWT, les concepteurs voulaient clairement marquerla différence avec l’interface Serializable de Java. En effet, cette dernière recouvreune sémantique plus complexe et différente de la sérialisation GWT, qui se veut plussimple et spécialisée. De plus, l’interface Serializable appartient au package java.io

qui ne fait pas partie des classes émulées par GWT.

Le risque de confusion existant, les concepteurs de GWT ont choisi de rendre ladifférence explicite en introduisant l’interface IsSerializable. Cependant, l’existencede ces deux interfaces complexifie la réutilisation de code qui utilise l’interface JavaSerializable. Par conséquent, depuis la version 1.4 de GWT, il est possible d’utiliseraussi l’interface Serializable pour dénoter une classe sérialisable pour GWT, avecune contrainte cependant : lors de la compilation, GWT génère un fichier .gwt.rpccontenant la politique de sérialisation, c’est­à­dire les types autorisés à la sérialisation ;ce fichier doit être déployé sur le serveur, faute de quoi le serveur peut refuser lasérialisation.

5.7 LES EXCEPTIONS

Lors d’un appel RPC, bien des raisons peuvent faire en sorte que l’appel n’aboutissepas : indisponibilité du réseau, impossibilité de joindre le serveur, erreur sur le serveurlors de l’exécution de la méthode... Ces conditions sont traitées par GWT RPC « entermes d’exceptions Java » ; la nuance est importante, car il ne s’agit pas d’exceptionsqui sont levées de façon classique.

En effet, rappelez-vous que l’appel à la méthode distante est asynchrone, ce quisignifie que, tout comme la disponibilité du résultat de l’appel, une éventuelle erreurse produisant lors de l’appel ne sera pas disponible immédiatement à la sortie de laméthode, mais à un moment ultérieur. Il est donc impossible de lever une exceptiondans la méthode appelée ; c’est pour cette raison que le callback qui est passé enparamètre lors de l’appel RPC doit définir, outre la méthode onSuccess(), une méthodeonFailure() qui accepte un paramètre de type Throwable. En cas d’erreur, c’est laméthode onFailure() qui sera invoquée en lieu et place de onSuccess(), avec commeparamètre l’exception traduisant la condition d’erreur.

Page 98: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

84 Chapitre 5. Communiquer avec le serveur

On le voit, il s’agit bien de traiter les cas d’erreurs au travers d’exceptions Java,puisque c’est bien une instance de Throwable qui est passée à onFailure(), mais sansqu’une exception Java ne soit levée côté client.

Les erreurs qui peuvent survenir lors d’un appel RPC peuvent être classées endeux catégories : les exceptions contrôlées (checked) et les exceptions non contrôlées(unchecked) :

• Les exceptions contrôlées sont celles qui sont explicitement déclarées parl’interface (synchrone) de votre service au moyen du mot-clé « throws ». Cesexceptions sont susceptibles de se produire lors de l’exécution de la méthodeappelée sur le serveur. Notez qu’ici c’est bien le mécanisme standard desexceptions Java qui s’applique, puisque l’implémentation de cette interfaces’exécute sous forme de code Java classique, côté serveur.

• Les exceptions non contrôlées sont toutes celles qui peuvent survenir en dehorsdu cas précédent, et qui traduisent des conditions anormales empêchant l’appelRPC de se terminer correctement et proprement.

GWT peut générer uniquement les exceptions non contrôlées suivantes :

• InvocationException est générée lorsque la requête ne parvient pas au serveur,pour une raison quelconque (réseau indisponible, échec de la résolution DNS,connexion impossible, etc.), ou bien lorsqu’une exception non contrôléesurvient lors de l’exécution de la méthode appelée (par exemple, NullPoin-terException). Dans ce dernier cas l’exception originale est encapsulée en tantque cause dans l’InvocationException.

• IncompatibleRemoteServiceException est générée lorsqu’un client essaye d’ac-céder à un service dont une version plus récente a été déployée sur le serveur.En général le simple fait de rafraîchir le client suffit à rétablir la situation.

Dans tous les cas, le traitement de l’exception par GWT est le même : au lieud’appeler la méthode onSuccess() du callback, c’est la méthode onFailure() qui estappelée, avec en paramètre l’exception survenue.

Tableau 5.1 — Synthèse des différents cas d’exception

Condition d’erreur Type de Throwable passée à onFailureException contrôlée t (de type T) survenantlors de l’exécution de la méthode sur leserveur

T

Exception non contrôlée t survenant lors del’exécution de la méthode sur le serveur

InvocationException avec cause = t

L’invocation du service n’a pas pu se faireou ne s’est pas terminée de façon propre

InvocationException

La version du service déployée sur le serveurest incompatible avec la version attendue

IncompatibleRemoteServiceException

Page 99: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

5.7 Les exceptions 85

Attention

Il serait erroné de penser que le fait qu’une InvocationException a été générée etpassée à la méthode onFailure() signifie que la méthode du service distant n’a pasété appelée ! En effet, il peut se produire une erreur après l’exécution de celle­ci, lorsde l’envoi de la réponse au client. Dans ce cas précis, une InvocationException seralevée, bien que la méthode ait été exécutée avec succès.

Une façon élégante de traiter les différents cas d’exception dans la méthodeonFailure() est de relancer l’exception qui a été reçue à l’intérieur du bloc try

d’un try-catch ; ainsi on peut utiliser le mécanisme habituel, comme dans l’exemplesuivant :

public void onFailure(Throwable caught) {try {

// relancer l’exception reçuethrow caught;

} catch (IncompatibleRemoteServiceException e) {// traiter le cas de l’incompatibilité

} catch (InvocationException e) {// traiter le cas de l’échec de l’appel

} catch (CheckedException1 e) {// une des exceptions déclarées par la méthode originale

} catch (CheckedException2 e) {// une autre des exceptions déclarées

} catch (Throwable e) {// en dernier ressort... toute autre exception

}}

Il est bien sûr possible de redéfinir ses propres exceptions en sous-classantException, mais il faut garder à l’esprit que le code de la classe, comme tout codetournant côté client, doit s’inscrire dans le sous-ensemble du JRE émulé par GWT. Enpratique, cela n’est pas une contrainte forte car les exceptions sont rarement des typescomplexes.

Page 100: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 101: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

DEUXIÈME PARTIE

Aller plus loin avecGWT

Page 102: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 103: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Internationalisation

6

ObjectifDans ce chapitre, nous allons voir comment rendre votre application facilementadaptable à d’autres langues et cultures ; et plus généralement, comment séparerproprement les ressources du code.

6.1 LES POSSIBILITÉSD’INTERNATIONALISATION DE GWT

L’internationalisation, aussi désignée i18n pour économiser quelques octets, est l’en-semble des techniques qui permettent de rendre un logiciel facilement adaptable àla langue et aux usages régionaux de l’utilisateur (ce qu’on appelle la locale). Uneapplication internationalisée peut alors être localisée, c’est-à-dire adaptée à une langueparticulière.

GWT possède un arsenal permettant de rendre une application facilementlocalisable, et ce dans différentes configurations : soit qu’il s’agisse de la simpletraduction de libellés ou de l’externalisation de paramètres, soit de l’externalisationde messages complexes avec des parties variables, soit de l’accès à des ressources déjàlocalisées. Le même mécanisme peut également être utilisé pour placer des propriétés(paramètres, etc.) dans des fichiers externes facilement accessibles depuis votre code,indépendamment de la locale.

La technique la plus simple est appelée internationalisation statique. Dans ce cas,les différents libellés et messages sont associés à des clés, chaque clé se traduit par uneméthode dans une interface et GWT fournit l’implémentation de cette interface lors

Page 104: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

90 Chapitre 6. Internationalisation

de l’exécution, en fonction de la locale choisie. Les chaînes correspondant aux cléssont stockées dans de simples fichiers texte similaires aux fichiers properties.

Il est également possible d’utiliser une technique d’internationalisation ditedynamique, qui permet d’accéder à un dictionnaire contenu dans la page HTML hôte.Cette méthode est dite dynamique car les clés de cette mappe ne sont pas forcémentconnues d’avance au moment de la compilation. Elle est particulièrement adaptée pourintégrer des composants GWT dans une application déjà internationalisée, lorsqueles messages localisés sont générés par le serveur et déjà présents dans la page HTML.

Enfin, il existe une technique générique (Localizable) qui permet de sélectionnerune implémentation spécifique d’une interface en fonction de la locale.

Nous ne détaillerons dans la suite que la méthode statique, qui est la plus simple àutiliser et la plus appropriée pour une application GWT « propre ».

6.1.1 Importer le module I18N

Toutes les fonctionnalités i18n de GWT dépendent d’un module nommé judicieuse-ment « I18N ». Par conséquent, pour utiliser une des classes que nous allons évoquer,il faudra toujours prendre la précaution de référencer ce module dans le fichier modulede votre application, en y incluant un élément XML inherits additionnel dansl’élément modules :

<module><!- - - - Les classes de base GWT--><inherits name=’com.google.gwt.user.User’/>

<!-- Autres modules référencés --><inherits name=’com.google.gwt.i18n.I18N’/>

<!-- Le point d’entrée --><entry-point class=’xxx.xxx.xxxx’/>

</module>

6.2 INTERNATIONALISATION « STATIQUE »

L’internationalisation statique repose sur la définition d’interfaces ; l’ensembledes clés servant d’index aux messages est donc connu au moment de la compilationGWT, ce qui permet au compilateur d’effectuer des optimisations. D’un autrecôté, le fait de devoir connaître à l’avance les clés de traduction peut être unelimitation ; dans ce cas peut-être que l’internationalisation dynamique est plusadaptée à ce que vous souhaitez faire.

Les interfaces permettant l’internationalisation statique sont Constants,ConstantsWithLookup et Messages. La première permet d’associer simplement deschaînes de caractères à des clés définies sous forme de méthodes dans une interface ;la seconde y ajoute la possibilité d’interroger une clé dynamique ; la troisième permetde générer des messages incluant des paramètres, à la manière de la classe native JavaMessageFormat.

Page 105: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 91

6.2.1 L’interface Constants

L’interface Constants est une interface « marqueur » destinée à être étendue. Sonutilisation est très simple :

• créer une interface qui étend Constants ;• définir les valeurs associées aux clés ;• accéder aux valeurs dans le code client.

Créer l’interface

Lorsque vous souhaitez externaliser certaines chaînes de caractères pour pouvoir leslocaliser, vous devrez donc tout d’abord créer une interface qui étend Constants. Danscette interface, vous déclarez une fonction par chaîne que vous souhaitez externaliser,par exemple pour les jours de la semaine :

package oge.gwt.chap63.client;import com.google.gwt.i18n.client.Constants;

public interface AppConstants extends Constants {String lun();String mar();String mer();String jeu();String ven();String sam();String dim();

}

Ce faisant, vous avez déclaré que vous alliez définir sept ressources externes,dont les clés seront respectivement « lun », « mar », « mer », « jeu », « ven »,« sam » et « dim ».

Définir les valeurs associées

Ensuite, il faut définir les valeurs associées à ces clés ; pour cela il faut écrire unfichier nommé interface.properties où interface est le nom de notre interface(AppConstants dans notre exemple).

Le contenu des fichiers .properties associés aux interfaces d’internationalisation deGWT est similaire à la notion de fichier properties de Java ; pour simplifier, il s’agitd’un fichier texte contenant en ensemble de lignes de la forme :

clé = valeur

Les fichiers .properties Java et GWT

À la différence des fichiers .properties Java natifs, les fichiers .properties de GWTdoivent être encodés en UTF­8 et supportent l’inclusion directe de caractères Unicode.Si vous allez afficher des caractères internationaux, assurez­vous que la page hôtecontient le tag méta suivant :<meta http-equiv="content-type"

content="text/html;charset=utf-8" />

Page 106: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

92 Chapitre 6. Internationalisation

Si on reprend notre exemple, il nous faut définir la valeur correspondant àchacune des sept clés « lun », « mar », « mer », etc. Cela donne un fichier AppCons-tants.properties contenant :

lun = lundimar = mardimer = mercredijeu = jeudiven = vendredisam = samedidim = dimanche

Ce fichier doit se trouver dans le même package que l’interface correspondante.

Accéder aux valeurs dans le code client

Pour accéder aux valeurs correspondant aux clés depuis le code client, on demandesimplement à GWT de nous fournir une implémentation de notre interface grâce àl’omniprésent GWT.create(). Par exemple on écrira :

AppConstants appConstants = GWT.create(AppConstants.class);

On obtient en retour une référence vers une implémentation de l’interface telleque les appels aux méthodes donnent en retour la valeur associée au travers du fichierproperties. Ainsi, appContants.lun() donnera « lundi », appConstants.mar() donnera« mardi », etc.

Notez que l’implémentation de cette interface est générée automatiquement parGWT, par conséquent vous ne devez normalement pas l’étendre directement.

Exemple

Voici un exemple d’utilisation de l’interface Constants. Les fichiers AppConstants.javaet AppConstants.properties sont tels que présentés plus haut.

On va simplement afficher le résultat de l’appel aux méthodes de l’interface dansune Grid. La page HTML sera très concise :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><!-- Chargement de l’appli --><script type="text/javascript" language="javascript"

src="gwtchap63/gwtchap63.nocache.js"></script></head>

<body><h1><p align="center">Internationalisation</p></h1><div id=’content’ align="center" />

</body></html>

Page 107: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 93

On définit un élément div avec un id qu’on référencera dans le code client.

Le code client va, lui, appeler GWT.create() pour récupérer la référence versl’implémentation de l’interface AppConstants, puis construire une Grid pour illustrerl’appel aux fonctions.

package oge.gwt.chap63.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;import com.google.gwt.user.client.ui.Grid;import com.google.gwt.user.client.ui.RootPanel;

public class GwtChap63 implements EntryPoint {

/*** Le point d’entrée.*/public void onModuleLoad() {

AppConstants appConstants = GWT.create(AppConstants.class);

RootPanel rootPanel = RootPanel.get("content");

final Grid grid = new Grid(7, 2);grid.setBorderWidth(1);grid.setCellPadding(5);grid.setCellSpacing(0);

int i =0;grid.setText(i, 0, "lun()");grid.setText(i++, 1, appConstants.lun());grid.setText(i, 0, "mar()");grid.setText(i++, 1, appConstants.mar());grid.setText(i, 0, "mer()");grid.setText(i++, 1, appConstants.mer());grid.setText(i, 0, "jeu()");grid.setText(i++, 1, appConstants.jeu());grid.setText(i, 0, "ven()");grid.setText(i++, 1, appConstants.ven());grid.setText(i, 0, "sam()");grid.setText(i++, 1, appConstants.sam());grid.setText(i, 0, "dim()");grid.setText(i++, 1, appConstants.dim());

rootPanel.add(grid);

}}

Page 108: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

94 Chapitre 6. Internationalisation

Enfin le fichier module, GwtChap63.gwt.xml :

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN""http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd"><module rename-to=’gwtchap63’>

<!-- inclure le module principal GWT --><inherits name=’com.google.gwt.user.User’/><!-- inclure le module d’internationalisation --><inherits name=’com.google.gwt.i18n.I18N’/>

<!-- Feuille de style standard--><inherits name=’com.google.gwt.user.theme.standard.Standard’/>

<!-- Point d’entrée --><entry-point class=’oge.gwt.chap63.client.GwtChap63’/>

</module>

Si tout est correctement configuré, vous pouvez exécuter l’application en modehôte (Run as > Web Application), et le résultat sera celui affiché en figure 6.1.

Figure 6.1 — Exécution de l’application

Autres types

L’externalisation n’est pas limitée à des chaînes de caractères ; elle peut s’appliquer àdifférents types. La déclaration dans l’interface doit toujours avoir la forme :

T méthode() ;

Où T est un des types autorisés selon le tableau 6.1.

Page 109: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 95

Tableau 6.1 — Types autorisés pour l’externalisation

T Interprétation de la valeur de la propriétéString Une chaîne de caractères sans traitement

String[] Une liste de chaînes séparées par des virgules. Utiliser \\, pour insérer unevirgule à l’intérieur d’une chaîne.

int Un entier (vérifié à la compilation)

float Un nombre compatible avec le type float (vérifié à la compilation)

double Un nombre compatible avec le type double (vérifié à la compilation)

boolean Un booléen représenté par true ou false (vérifié à la compilation)

Map Une liste de clés séparées par des virgules. La Map sera constituée de l’ensembledes paires clé à valeur. Par exemple, si le fichier properties contient :dico=k1,k2,k3k1=v1k2=v2k3=v3

alors la méthode Map dico() retournera une Map telle que k1àv1, k2à v2 etk3 à v3.

Par exemple, il peut être plus judicieux de représenter les jours de la semaine dansun tableau de String. On pourra ainsi redéfinir l’interface AppConstants comme suit :

package oge.gwt.chap63.client;import com.google.gwt.i18n.client.Constants;

public interface AppConstants extends Constants {String[] jours();

}

Le fichier AppConstants.properties sera réécrit comme suit :

jours = lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche

L’utilisation devient alors :

package oge.gwt.chap63.client;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;import com.google.gwt.user.client.ui.Grid;import com.google.gwt.user.client.ui.RootPanel;

public class GwtChap63 implements EntryPoint {

/*** Le point d’entrée.*/public void onModuleLoad() {

AppConstants appConstants = GWT.create(AppConstants.class);

RootPanel rootPanel = RootPanel.get("content");

final Grid grid = new Grid(7, 2);grid.setBorderWidth(1);

Page 110: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

96 Chapitre 6. Internationalisation

grid.setCellPadding(5);grid.setCellSpacing(0);

String[] jours = appConstants.jours();for (int i = 0; i < 7; i++) {

grid.setText(i, 0, "jours[" + i + "]");grid.setText(i, 1, jours[i]);

}

rootPanel.add(grid);

}}

Le résultat est présenté en figure 6.2.

Figure 6.2 — Le résultat avec un tableau de strings

6.2.2 Gestion des locales multiples

Dans l’exemple précédent, on a externalisé un certain nombre de chaînes de caractèresau moyen de l’interface Constants, mais les valeurs retournées ne dépendaient pasd’une locale particulière. Pour fournir les différentes traductions ou variantes localescorrespondant à une interface Constants, il faut créer différents fichiers propertiesnommés de la façon suivante :

interface_locale.properties

où interface est le nom de votre interface (AppConstants dans notre exemple), etlocale un identifiant d’environnement régional ou « locale ».

Page 111: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 97

Locale ou paramètres régionaux

Le terme « locale » est un anglicisme désignant, en informatique, l’ensemble desparamètres qui définissent la langue et les préférences culturelles qui influencent uneinterface utilisateur. La traduction la plus proche est « paramètres régionaux », maispar abus de langage on désigne souvent par « locale » l’identifiant qui la représente ;c’est pourquoi on a choisi de conserver le terme de « locale » dans la suite.

L’identifiant de locale est composé de :

• soit un code de langue à deux caractères (par ex. fr pour le français, en pourl’anglais, de pour l’allemand, etc.) ;

• soit un code langue complété d’un code pays à deux lettres, pour tenir comptedes variantes entre pays partageant une langue (par ex. fr_FR pour le françaisen France, fr_CA pour le français au Canada.

Les codes langue et pays

Le code langue utilisé dans la désignation de la locale est le code ISOà deux lettres nommé ISO 639­1, dont on peut trouver une liste surhttp://fr.wikipedia.org/wiki/Liste_des_codes_ISO_639­1. Le code pays utiliséest le code ISO à deux lettres ISO 3166­1, dont on peut trouver une liste surhttp://fr.wikipedia.org/wiki/ISO_3166­1. À noter que l’usage est de représenter lecode langue en minuscules et le code pays en majuscules, mais GWT n’oblige pas àcela, de même qu’il ne vérifie pas l’existence réelle des codes utilisés mais fournitseulement un mécanisme.

Les valeurs retournées par l’instance de l’interface fournie par GWT.create() sontdéterminées comme suit (xx et YY représentent respectivement un code langue et uncode pays).

Tableau 6.2 — Valeurs retournées par GWT.create

Locale courante Source des valeurs retournéesNon spécifiée Interface.properties

xx Interface_xx.properties s’il existe et contient la propriétérecherchée, sinon comme pour « locale non spécifiée »

xx_YY Interface_xx_YY.properties s’il existe et contient la propriétérecherchée, sinon comme pour « locale xx»

Il faut noter que l’algorithme de recherche de valeur est appliqué indépendammentpour chaque clé, c’est-à-dire que ce n’est pas un fichier properties dans son ensemblequi est choisi, mais chaque valeur sera extraite de la source la plus appropriée.

Page 112: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

98 Chapitre 6. Internationalisation

L’outil i18nCreator

Si vous avez déjà sous la main un ou des fichiers properties contenant des traductionsque vous souhaitez réutiliser, ou si vous préférez gérer les fichiers properties comme« maître » (et non l’interface), l’outil i18nCreator peut vous aider ; en effet, il crée desscripts qui permettent de générer automatiquement une interface de type Constants àpartir d’un fichier properties. Lorsque ce dernier change, il suffit de relancer les scriptspour mettre à jour l’interface. i18nCreator est un des outils en ligne de commande quifont partie de la distribution standard de GWT ; pour plus de détails sur son utilisation,référez­vous à l’aide en ligne.

Lorsque des traductions adaptées à différentes locales ont été établies au moyen defichiers properties tel que décrit ci-dessus, il faut encore effectuer deux étapes :

• déclarer les locales additionnelles dans le fichier module ;• donner un moyen à GWT de savoir quelle est la locale en cours, afin que la

méthode GWT.create() puisse fournir une implémentation de l’interface prenanten compte cette locale.

Déclarer les locales dans le fichier de module XML

Les locales additionnelles sont déclarées au moyen de l’élément extend-proterty. Ildoit être répété autant de fois que de locales définies, par exemple pour inclure deslocalisations en anglais et allemand, on écrira :

<!-- Locales à inclure --><extend-property name="locale" values="en"/><extend-property name="locale" values="de"/>

Attention car chaque locale supplémentaire déclarée fait augmenter le nombrede permutations à compiler, c’est-à-dire de couples « navigateur cible/locale ». Notezqu’il existe toujours au moins une locale à compiler qui est la locale par défaut,bien que celle-ci ne soit pas déclarée dans le fichier du module. Par conséquent, endéclarant deux locales supplémentaires, on a en fait multiplié par trois le nombre depermutations à compiler !

Spécifier la locale

Il reste maintenant à dire à GWT quelle est la locale à utiliser lors de l’exécution del’application. Pour cela il existe deux moyens : soit un tag meta dans la page HTMLhôte, soit un paramètre dans l’URL de la page.

Page 113: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 99

Pour spécifier la locale dans la page HTML hôte, il faut insérer un élément metade la forme suivante :

<metaname="gwt:property"content="locale=xx">

ou :

<metaname="gwt:property"content="locale=xx_YY">

Par exemple, pour utiliser la locale allemande on utilisera :

<meta name="gwt:property" content="locale=de">

Pour spécifier la locale dans l’URL, on ajoutera un paramètre de la requête nommélocale et qui prendra la valeur de la locale souhaitée, par exemple :

http://localhost:8080/GwtChap63.html?locale=en

Lorsque les deux méthodes sont utilisées en même temps, c’est la locale spécifiéedans l’URL qui a la priorité.

Exemple

Reprenons l’exemple initial et ajoutons-y les locales « anglais » (en) et « allemand »(de). L’interface AppConstants ne change pas :

package oge.gwt.chap63.client;

import com.google.gwt.i18n.client.Constants;

public interface AppConstants extends Constants {String lun();String mar();String mer();String jeu();String ven();String sam();String dim();

}

Le fichier contenant les valeurs par défaut, AppConstants.properties, ne changepas non plus et contiendra les valeurs pour le français :

lun = lundimar = mardimer = mercredijeu = jeudiven = vendredisam = samedidim = dimanche

Page 114: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

100 Chapitre 6. Internationalisation

À côté de cela, on va créer un fichier pour chacune des locales supplémentaires ;AppConstants_en.properties pour l’anglais :

lun = mondaymar = tuesdaymer = wednesdayjeu = thursdayven = fridaysam = saturdaydim = sunday

Et AppConstants_de.properties pour l’allemand :

lun = Montagmar = Dienstagmer = Mittwochjeu = Donnerstagven = Freitagsam = Samstagdim = Sonntag

N’oublions pas d’ajouter ces deux locales nouvelles dans le fichier module XML :

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN""http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">

<module rename-to=’gwtchap63’><!-- inclure le module principal GWT --><inherits name=’com.google.gwt.user.User’/><!-- inclure le module d’internationalisation --><inherits name=’com.google.gwt.i18n.I18N’/>

<!-- Feuille de style standard--><inherits name=’com.google.gwt.user.theme.standard.Standard’/><!-- Locales à inclure -->

<extend-property name="locale" values="en"/>

<extend-property name="locale" values="de"/>

<!-- Point d’entrée --><entry-point class=’oge.gwt.chap63.client.GwtChap63’/>

</module>

Le code de l’application, lui, ne change pas du tout (c’est bien là un des objectifsde l’internationalisation).

Reste à spécifier la locale à utiliser. Si on ne change rien à la page HTML hôte, cesont les traductions françaises qui seront utilisées, puisque celles-ci sont dans le fichierproperties par défaut.

Page 115: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 101

On va maintenant ajouter un tag meta dans la page HTML hôte pour spécifier lalocale allemande ; le code HTML de la page devient :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html><head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8"><!-- Spécifier la locale à utiliser -->

<meta name="gwt:property" content="locale=de">

<!-- Chargement de l’appli --><script type="text/javascript" language="javascript"

src="gwtchap63/gwtchap63.nocache.js"></script></head>

<body><h1><p align="center">Internationalisation</p></h1><div id=’content’ align="center" />

</body></html>

Si on lance l’application, le résultat est tel que ce ne sont plus les valeurs françaisesissues du fichier AppConstants.properties qui sont affichées, mais bien les valeursallemandes issues du fichier AppConstants_de.properties (figure 6.3).

Figure 6.3 — Résultat avec la locale « de » issue d’un tag méta de la page hôte

Page 116: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

102 Chapitre 6. Internationalisation

On peut facilement passer à la locale anglaise en ajoutant ?locale=en dans l’URLdu navigateur, même en mode hôte (figure 6.4).

Figure 6.4 — Résultat avec la locale « en » issue d’un paramètre de l’URL

6.2.3 Annotations

L’interface Constants possède encore d’autres secrets ; ainsi il est possible de spécifierdirectement des valeurs par défaut dans l’interface elle-même, au moyen d’annotationsJava.

Par exemple, on peut réécrire l’interface initiale de notre exemple de la façonsuivante :

package oge.gwt.chap63.client;import com.google.gwt.i18n.client.Constants;

public interface AppConstants extends Constants {@DefaultStringValue("lundi")String lun();@DefaultStringValue("mardi")String mar();@DefaultStringValue("mercredi")String mer();@DefaultStringValue("jeudi")String jeu();@DefaultStringValue("vendredi")String ven();@DefaultStringValue("samedi")String sam();@DefaultStringValue("dimanche")String dim();

}

Page 117: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.2 Internationalisation « statique » 103

On peut alors se passer totalement du fichier AppConstants.properties, les valeursassociées aux clés seront directement tirées de l’interface. Toutefois, en présence d’unou plusieurs fichiers properties, ce sont ces derniers qui auront priorité, selon les règlesénoncées plus haut.

L’utilisation des annotations pour spécifier les valeurs par défaut, en plus de ne pasnécessiter la création d’un fichier supplémentaire, permet d’utiliser des constantes Javaet expressions constantes, et de ne pas se préoccuper de l’interprétation des caractèresspéciaux dans les valeurs.

On peut également, grâce aux annotations, modifier la clé de recherche (le nomde la propriété) dans les fichiers properties. Par défaut, la clé est identique au nomde la méthode dans l’interface, ainsi la méthode lun() utilisera la clé « lun » pourrechercher la valeur associée dans les différentes locales. Pour modifier cette clé derecherche, il suffit d’annoter la méthode avec @Key(cle), par exemple :

@Key("labels.jours.lun")String lun();@Key("labels.jours.mar")String mar();@Key("labels.jours.mer")String mer();@Key("labels.jours.jeu")String jeu();@Key("labels.jours.ven")String ven();@Key("labels.jours.sam")String sam();@Key("labels.jours.dim")String dim();

Le fichier properties devra alors utiliser les clés renommées :

labels.jours.lun = lundilabels.jours.mar = mardilabels.jours.mer = mercredilabels.jours.jeu = jeudilabels.jours.ven = vendredilabels.jours.sam = samedilabels.jours.dim = dimanche

6.2.4 L’interface ConstantsWithLookup

Constants offre une possibilité précieuse d’externaliser des valeurs et de les rendredépendants de la locale ; cependant, on ne peut accéder à ces valeurs qu’en appelant laméthode associée de l’interface. Ainsi, dans notre exemple précédent, la seule manièred’accéder au nom d’un jour de la semaine est d’appeler une des méthodes lun(), mar(),mer(), jeu(), ven() sam() ou dim() ; il est impossible d’accéder à la valeur d’une cléqui serait contenue dans une String.

Page 118: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

104 Chapitre 6. Internationalisation

C’est pour autoriser cette possibilité qu’a été conçue l’interface ConstantsWithLoo-

kup. Cette interface s’utilise exactement comme Constants (qu’elle étend d’ailleurs),mais ajoute des méthodes pour obtenir la valeur associée à une clé dont le nom estcontenu dans une String :

• boolean getBoolean(String)

• double getDouble(String)

• float getFloat(String)

• int getInt(String)

• Map<String, String> getMap(String)

• String getString(String)

• String[] getStringArray(String)

Attention

Le paramètre passé aux méthodes de ConstantsWithLookup n’est pas le nom de la cléutilisée dans le fichier properties associé, mais celui de la méthode de l’interface...Ces noms peuvent différer dans le cas où l’annotation @Key est utilisé.

En règle générale, si on n’a pas besoin de la fonctionnalité offerte par Constants-WithLookup, il est préférable d’utiliser Constants car cette dernière se prête mieux àl’optimisation.

6.2.5 L’interface Messages

Comme Constants, Messages est une interface « marqueur » qui s’utilise d’une façonsimilaire. Cependant, à la différence de Constants, les méthodes qu’on place dans uneinterface qui étend Messages peuvent accepter un nombre quelconque de paramètres ;en contrepartie, les valeurs associées aux clés au travers des fichiers properties peuventinclure des parties variables, désignées par {0}, {1}, etc.

Le format supporté est identique à celui des patterns de la classenative Java MessageFormat. S’il est simple à comprendre pour des castriviaux, ce format est toutefois très riche et permet des formatagescomplexes. Il est décrit en détail dans la Javadoc de la classe MessageFormat :http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html

Lorsqu’une méthode d’une interface qui étend Messages est appelée, les partiesvariables sont remplacées par la valeur des paramètres de la méthode, convertis enString. Elles peuvent figurer dans un ordre quelconque : {0} fera toujours référence aupremier paramètre de la méthode, quelle que soit sa position dans le message ; {1} audeuxième, etc.

Page 119: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

6.3 Le formatage des dates et nombres 105

6.3 LE FORMATAGE DES DATES ET NOMBRES

Comme on l’a mentionné au § 3.2.2 Émulation des classes du JRE, la bibliothèqued’émulation JRE de GWT ne contient pas les classes java.text.DateFormat,java.text.DecimalFormat, java.text.NumberFormat, java.TimeFormat,etc. Cependant, un sous-ensemble de la fonctionnalité de ces classes estfourni par les classes com.google.gwt.i18n.client.NumberFormat etcom.google.gwt.i18n.client.DateTimeFormat.

Une différence importante est que les classes natives Java sont capables de travailleravec plusieurs locales différentes durant l’exécution, alors que la sélection de la localese fait une fois pour toutes au lancement de l’application, de la même façon quela sélection des messages associés aux interfaces de type Constants ou Messages, autravers du mécanisme de Deferred Binding.

Pour utiliser ces classes, il faudra également hériter le module I18N en ajoutant laligne suivante dans le fichier module :

<inherits name=’com.google.gwt.i18n.I18N’/>

6.3.1 NumberFormat

Pour formater un nombre, il faut tout d’abord obtenir une instance de NumberFormat ;on utilise pour cela une des méthodes statiques getXxxFormat(), qui retourne uneinstance de NumberFormat appropriée à générer une représentation d’un nombre.

Tableau 6.3 — Méthodes pour le formatage d’un nombre

Méthode Format que génère le formateur obtenugetCurrencyFormat() montant dans la locale courante

getDecimalFormat() nombre au format décimal dans la locale courante

getPercentFormat() pourcentage dans la locale courante

getScientificFormat() nombre au format scientifique standard dans la locale courante

getFormat(Stringpattern)

format personnalisé défini par le pattern spécifié.Le format de la spécification du pattern est décrit dans laJavadoc de la classe NumberFormat : http://google­web­toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/i18n/client/NumberFormat.html

La méthode format(double) peut alors être utilisée sur l’instance de NumberFormat

obtenue pour produire une chaîne formatée selon le format voulu. Inversement, onpeut aussi utiliser la méthode parse(String) qui lit un nombre dans une chaîne decaractères.

Page 120: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

106 Chapitre 6. Internationalisation

6.3.2 DateTimeFormat

La classe DateTimeFormat fonctionne de façon similaire à NumberFormat, pour les dateset heures. Les différentes méthodes retournent donc une instance de DateTimeFormat

appropriée à générer une représentation d’une date.

Tableau 6.4 — Méthodes pour le formatage d’une date

Méthode Format que génère le formateur obtenugetFullDateFormat() date au format complet dans la locale courante

getFullDateTimeFormat() date et heure au format complet dans la locale courante

getFullTimeFormat() heure au format complet dans la locale courante

getLongDateFormat() date au format long dans la locale courante

getLongDateTimeFormat() date et heure au format long dans la locale courante

getLongTimeFormat() heure au format long dans la locale courante

getMediumDateFormat() date au format médian dans la locale courante

getMediumDateTimeFormat() date et heure au format médian dans la locale courante

getMediumTimeFormat() heure au format médian dans la locale courante

getShortDateFormat() date au format court dans la locale courante

getShortDateTimeFormat() date et heure au format court dans la locale courante

getShortTimeFormat() heure au format court dans la locale courante

getFormat(String pattern) format personnalisé défini par le pattern spécifié.Le format de la spécification du pattern est décrit dans laJavadoc de la classe DateTimeFormat : http://google­web­toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/i18n/client/DateTimeFormat.html

La méthode format(Date) peut alors être utilisée sur l’instance de DateTimeFormat

obtenue pour produire une chaîne formatée selon le format voulu. Inversement, onpeut aussi utiliser la méthode parse(String) qui lit une Date dans une chaîne decaractères.

Page 121: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Mécanismes avancés ducompilateur

7

ObjectifCe chapitre vous montrera comment mettre en œuvre deux fonctionnalités avancéesdu compilateur GWT :

D’une part JSNI (JavaScript Native Interface), qui prévoit la possibilité d’intégrer dansvotre propre code GWT du code JavaScript écrit à la main.

D’autre part le Deferred Binding, mécanisme par lequel le compilateur génèredifférentes variantes de code JavaScript, dont une seule sera chargée à l’exécution.

Le compilateur GWT est au centre de l’architecture de GWT, et la viabilitédu toolkit dépend grandement de son efficacité ; à ce titre, il effectue un travailremarquable et discret d’optimisation. Les concepteurs de GWT y ont donc inclut desfonctionnalités aussi astucieuses qu’efficaces : JSNI pour faciliter l’interfaçage avecles bibliothèques JavaScript, et le Deferred Binding pour optimiser et adapter le codespécifiquement en fonction de l’environnement d’exécution. Nous allons détailler cesdeux points.

Page 122: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

108 Chapitre 7. Mécanismes avancés du compilateur

7.1 JSNI (JAVASCRIPT NATIVE INTERFACE)

7.1.1 Le principe

Bien que cela semble aller à l’opposé de la philosophie de GWT, il existe des situationsoù il est souhaitable de pouvoir intégrer dans une classe Java/GWT du code JavaScriptécrit à la main (par opposition au code généré par le compilateur GWT), par exemple :

• pour accéder à des fonctionnalités du navigateur qui ne sont pas exposées parles API GWT ;

• pour s’interfacer avec une bibliothèque JavaScript tierce.

C’est pour répondre à ces problématiques que GWT propose une fonctionnalitédite JSNI (JavaScript Native Interface). JSNI s’inspire de JNI (Java Native Interface), latechnique utilisée par Java pour exécuter du code qui n’est pas écrit en Java, adaptéeau cas particulier de GWT.

En ouvrant la porte à du code JavaScript écrit à la main, JSNI offre unformidable potentiel, mais par la même occasion rend le code dans lequel il estintégré potentiellement moins portable entre navigateurs, plus sujet aux fuitesmémoire, moins apte à être traité par les outils Java, et plus difficile à optimiserpar le compilateur GWT. Par conséquent, l’utilisation de JSNI doit être réservéeaux cas où il n’existe pas de meilleure option.

7.1.2 Écrire une méthode JSNI

Une méthode JSNI s’écrit simplement de la façon suivante :

• elle est précédée du mot-clé native ;• le code JavaScript est contenu dans un bloc de commentaires encadré par /*-{

et }-*/, situé entre la parenthèse fermante et le point-virgule.

Exemple :

public static native void alert(String msg) /*-{$wnd.alert(msg);

}-*/;

Ici on fait appel à la méthode alert(), qui est une méthode native de JavaScript.Notez qu’on doit utiliser $wnd pour faire référence à l’objet Window. De même, pourfaire référence à l’objet Document, on doit utiliser $doc.

7.1.3 Accéder à des objets Java depuis JSNI

Le code JavaScript inclus dans une méthode JSNI peut également manipuler des objetsJava. Les paramètres passés aux méthodes JSNI peuvent être désignés directement(comme le paramètre msg dans l’exemple ci-dessus). Attention toutefois aux règles depassage de paramètre qui s’appliquent dans le sens JavaScript > Java comme Java >JavaScript ; ces règles seront détaillées plus loin.

Page 123: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

7.1 JSNI (JavaScript Native Interface) 109

L’invocation d’une méthode Java nécessite l’utilisation d’une syntaxe spécifique :

[instance.]@classe::méthode(signature)(arguments)

Où :

• instance est l’instance sur laquelle porte l’appel (à omettre pour appeler uneméthode statique) ;

• classe est le nom qualifié de la classe (précédé du nom du package) ;• méthode est le nom de la méthode à appeler ;• signature est le profil de la méthode, afin de distinguer les

éventuelles variantes surchargées. Ce profil doit être encodé selon lesspécifications JNI (chapitre 3 de la spécification JNI, accessible ici :http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html# wp276) ;

• arguments est la liste des valeurs des arguments à passer à la méthode.

Le tableau 7.1 résume la codification à utiliser pour spécifier les profils de méthodes.

Tableau 7.1 — Codification de spécification des profils de méthodes

Type Java Code de lasignature

boolean Z

byte B

char C

short S

int I

long J

float F

double D

String Ljava/lang/String;

Xxx Laaa/bbb/ccc/Xxx;

...[] [...

Exemple (sans paramètres) :

public native String toStringJS() /*-{return [email protected]::toString()();

}-*/;

Exemple (avec paramètres) :

public native void something() /*-{[email protected]::setValue(

Ljava/lang/String;I)("Hello", 2);}-*/;

Page 124: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

110 Chapitre 7. Mécanismes avancés du compilateur

Il est également possible d’accéder à des variables avec une syntaxe similaire :

[instance.]@classe::variable

Où :

• instance est l’instance à laquelle on accède (à omettre pour accéder à unevariable statique) ;

• classe est le nom qualifié de la classe (précédé du nom du package) ;• variable est le nom de la variable.

7.1.4 Règles de passage de paramètres

À cause des différences de gestion des types entre Java et JavaSript, certaines règlesdoivent être respectées lors du passage de paramètres de et vers une méthode JSNI(tableau 7.2).

Le passage de long dans un sens ou dans l’autre est interdit, car JavaScript nesupporte pas de type équivalent. On peut si c’est nécessaire passer un objet de typeLong, qui sera traité de façon opaque comme tous les types non reconnus, c’est-à-direqu’il pourra uniquement être passé en retour lors de l’appel à une méthode Java.

7.1.5 Traitement des exceptions

Les exceptions se produisant dans du code JavaScript issu d’une méthode JSNIremontent tout comme une exception Java ; cependant si une telle exception est« catchée » par un bloc try-catch dans du code Java, elle est convertie en uneJavaScriptException, qui ne contient que le nom de la classe et la description del’erreur. Par conséquent, il est toujours préférable de traiter les exceptions JavaScriptdans le code JavaScript.

En revanche, si une exception Java se produit, même dans une méthode Javaappelée depuis une méthode JavaScript, l’exception conserve son intégrité lorsqu’elleremonte.

7.2 DEFERRED BINDING

7.2.1 Principes

Comme on l’a déjà mentionné, lors de la compilation GWT, le compilateur génèreplusieurs versions du code JavaScript pour prendre en compte les différences entre lesnavigateurs existants ; lors du chargement de l’application, c’est la version adaptéequi est chargée.

Ce mécanisme est en fait totalement générique, et ne se limite pas à la priseen compte des différents navigateurs. GWT offre en effet la possibilité de générerplusieurs versions du code JavaScript lors de la compilation, sachant qu’une seule doitêtre chargée lors de l’exécution. Le terme « Deferred Binding » (liaison différée) fait

Page 125: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

7.2 Deferred Binding 111

Tab

leau

7.2

—R

ègle

sde

pass

age

depa

ram

ètre

deet

vers

les

mét

hode

sJS

NI

Typ

eJa

vaSe

ns

Java

vers

Java

Scri

pt

(ce

qu

iest

reçu

dan

sle

cod

eJa

vaSc

rip

t)

Sen

sJa

vaSc

rip

tve

rsJa

va(c

eq

uid

oit

être

pas

sép

arle

cod

eJa

vaSc

rip

t)String

Une

chaî

nede

cara

ctèr

esJa

vaSc

ript

Une

chaî

nede

cara

ctèr

esJa

vaSc

ript

boolean

Une

vale

urbo

olée

nne

Java

Scrip

tU

neva

leur

bool

éenn

eJa

vaSc

ript

long

Inte

rdit

Inte

rdit

Aut

rety

penu

mér

ique

prim

itif(int,

short,

byte

,char,

float,

double

)U

neva

leur

num

ériq

ueJa

vaSc

ript

Une

vale

urnu

mér

ique

Java

Scrip

t

Tabl

eau

Java

Val

eur

opaq

ue(n

epe

utpa

sêt

rem

anip

ulé

mai

spe

utêt

rere

pass

éà

une

mét

hode

Java

)

Obj

et(r

eçu

enpa

ram

ètre

)

JavaScriptObject

JavaScriptObject

(pro

vena

ntde

code

Java

Scrip

t)U

nob

jetn

atif

Java

Scrip

tque

lcon

que

Tout

autr

ety

peV

aleu

rop

aque

,acc

essibl

egr

âce

àla

synt

axe

spéc

iale

décr

itepl

usha

utO

bjet

(reç

uen

para

mèt

re)

Page 126: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

112 Chapitre 7. Mécanismes avancés du compilateur

référence au fait que l’opération de sélection de la version de code à charger s’effectueau démarrage de l’application, par opposition à ce que serait une liaison totalementstatique (le code est lié lors de la compilation) ou totalement dynamique (le code estchargé dynamiquement au besoin, comme c’est le cas dans la JVM standard grâce auclass loader).

C’est ce mécanisme qui est mis en œuvre dans les techniques d’internationalisation« statique » à base d’interfaces (voir § 6.2 Internationalisation « statique »). Auminimum, le compilateur génère une version de code par navigateur cible, mais lorsqueplusieurs locales sont déclarées, le compilateur examine toutes les combinaisons(Firefox + français, Firefox + anglais, IE + français, IE + anglais, etc.) et génère uneversion de code optimisée pour chaque combinaison.

Le résultat est un temps de chargement optimal, puisque seul le code nécessairepour l’environnement de l’utilisateur est téléchargé. En outre, il n’y a pas de tempsperdu à rechercher une implémentation particulière lors de l’exécution, puisque toutesles implémentations sont déjà connues à la compilation. Revers de la médaille, lestemps de compilation peuvent devenir sensiblement longs lorsque le nombre decombinaisons augmente.

Le mécanisme de Deferred Binding est mis en jeu explicitement lorsque le code faitappel à la méthode GWT.create() ; cette méthode permet d’instancier une classe, maisà la différence de l’utilisation classique de new, elle indique au compilateur GWT quela classe spécifiée en paramètre peut être remplacée par une autre implémentation,selon le contexte de l’utilisateur. Le compilateur GWT créera alors une variantesupplémentaire du code JavaScript pour toutes les substitutions possibles de la classespécifiée. Évidemment, pour que le compilateur GWT puisse déterminer les variantes,il doit connaître cette classe lors de la compilation, c’est pourquoi le paramètre deGWT.create() doit être une constante (du type MyClass.class) et ne peut pas être unevariable.

7.2.2 Mise en oeuvre du Deferred Binding

Il existe deux façons de fournir une implémentation alternative à une classe instanciéepar GWT.create() :

• par substitution : la classe est remplacée par une autre selon des règles spécifiéesdans le fichier module ;

• par génération : les différentes variantes de l’implémentation fournie sontgénérées lors de la compilation GWT par un « générateur ».

Substitution

La méthode par substitution est la plus simple à utiliser, puisqu’il suffit d’ajouterquelques directives au fichier module. Pour comprendre, illustrons-la par un exemple.

Supposons que notre code client fasse appel à une classe MaClasse en l’instanciantvia GWT.create() :

MaClasse impl = GWT.create(MaClasse.class);

Page 127: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

7.2 Deferred Binding 113

Si on souhaite par exemple fournir une implémentation différente de MaClasse,pour une raison quelconque, lorsque le navigateur de l’utilisateur est IE 6, on crée uneclasse MaClasseIE6, qui étend MaClasse. On ajoute ensuite les lignes suivantes dans lefichier module :

<module><!-- ... --><!-- implémentation spécifique pour IE6 --><replace-with class="oge.gwt.client.GWtTest.MaClasseIE6"><when-type-is class=" oge.gwt.client.GWtTest.MaClasse"/><when-property-is name="user.agent" value="ie6" /></replace-with>

</module>

Avec cette configuration, l’appel à GWT.create(MaClasse.class) sera remplacé parle compilateur GWT par une instanciation de MaClasseIE6 dans toutes les variantesdestinées à IE 6 (valeur de la propriété user.agent).

Génération

Dans la méthode par substitution, les différentes variantes d’une classe existent entant que classe à part entière dans le code source, et le compilateur GWT décide del’implémentation à inclure dans le code généré selon le contexte de la compilation. Paropposition, dans la méthode par génération, le code source à utiliser comme implémen-tation est généré par une instance de la classe com.google.gwt.core.ext.Generator.

Supposons qu’au lieu de remplacer notre classe MaClasse par une implémentationspécifique, on souhaite faire générer l’implémentation par un générateur. On écriradans le fichier module :

<module><!-- ... --><generate-with class="oge.gwt.client.GwtTest.MaClasseGenerator"><when-type-assignable class=" oge.gwt.client.GwtTest.MaClasse" /></generate-with>

</module>

Cette directive indique au compilateur que lorsque le code source fait appelà GWT.create() pour instancier MaClasse (ou une sous-classe de celle-ci), alorsl’implémentation à utiliser sera fournie par l’invocation de la méthode generate() dugénérateur MaClasseGenerator.

L’implémentation d’un générateur est une tâche complexe qui dépasse largementla portée de cet ouvrage. Si vous souhaitez obtenir plus de détails sur la façond’implémenter un générateur, reportez-vous à la documentation en ligne.

Developper’s Guide

http://code.google.com/webtoolkit/doc/1.6/DevGuide.htmlSection « Coding Basics »

Page 128: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 129: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Le mécanisme d’historiquede GWT

8

ObjectifNous allons voir comment GWT résout le problème récurrent dans les applicationsAJAX de la gestion des boutons Précédent et Suivant du navigateur.

8.1 LE PROBLÈME

Les applications AJAX fonctionnent sur un principe d’interaction qui tend à imitercelui des applications de bureau traditionnelles. Cependant, ces applications sont leplus souvent hébergées dans une page HTML hôte unique, à l’intérieur d’un navigateurweb, pour lequel les utilisateurs sont accoutumés à un principe d’interaction différent.Dans le monde du Web traditionnel, un clic sur un lien peut être renversé par unappui sur le bouton de retour arrière du navigateur. Or, si une application AJAX neprend pas de précaution, un appui sur le bouton de retour arrière du navigateur peutêtre catastrophique en ramenant le navigateur sur la page web précédente, faisant dumême coup perdre tout travail effectué dans l’application AJAX.

Page 130: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

116 Chapitre 8. Le mécanisme d’historique de GWT

8.2 L’APPROCHE DE GWT

Heureusement, GWT offre une technique qui permet d’éviter ce désagrément, et quirend pleinement fonctionnels les boutons précédent/suivant du navigateur, moyennanttout de même un léger travail de la part du programmeur.

8.2.1 URL et fragment

Le mécanisme d’historique de GWT s’appuie sur la notion de « fragment » d’URL.Comme on l’a vu au chapitre 1, une URL quelconque peut éventuellement êtrecomplétée d’une partie optionnelle précédée du signe # appelée « fragment » ; cettechaîne de caractères est prévue à l’origine pour désigner une sous-partie du documentréférencé par l’URL. En pratique, le fragment est habituellement utilisé pour désignerun signet à l’intérieur de la page HTML, par exemple un début de paragraphe, pourpermettre d’y accéder directement.

Un des points intéressants à propos de ce fragment est que lorsqu’on active unlien pour lequel seul le fragment change par rapport à l’URL courante, le navigateurne recharge pas la page (il suppose qu’elle est déjà chargée). En revanche cela créebien une entrée dans l’historique du navigateur. Par conséquent, si une applicationJavaScript contenue dans la page est capable de détecter les changements de cefragment, elle pourra réagir aux appuis sur précédent ou suivant. C’est sur ce principeque fonctionne le mécanisme d’historique de GWT.

8.2.2 Encoder l’état de l’application

La contrainte qui en découle est que l’application doit être capable d’encoder son étatinterne, ou tout au moins chaque état pour lequel on souhaite pouvoir naviguer grâceaux boutons précédent/suivant, dans une chaîne de caractères qui sera stockée dans lapartie « fragment » de l’URL ; c’est ce que GWT appelle un « history token » (jetond’historique). Bien entendu, l’application doit également être capable de décoder cetoken, pour se remettre dans l’état correspondant au moment où le token a été généré.

Il faut souligner que le contenu et le format de ce token sont totalement à lacharge de l’application (donc du programmeur) ; en effet, GWT ne peut pas savoirquelles informations seront nécessaires pour rétablir l’application, car cela dépendentièrement de la structure de celle-ci. Dans les cas très simples, le token peut consistersimplement en une constante qui désigne un écran sur lequel se placer, mais dansles cas plus complexes, il devra contenir toute l’information nécessaire à restaurer lecontexte.

Il faut noter également que c’est à l’application de décider des « points desauvegarde », c’est-à-dire à quel moment créer une entrée dans l’historique. En effet,chaque clic ne doit pas donner lieu systématiquement à un point de retour, et iciencore GWT n’a pas de moyen de savoir quel clic entraîne un changement d’étatsignificatif tel qu’il doive donner lieu à la création d’une entrée d’historique.

Page 131: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

8.3 Un exemple 117

8.2.3 Mise en oeuvre

La mise en œuvre du mécanisme d’historique de GWT nécessite l’inclusion du codesuivant dans la page HTML hôte :

<iframe src="javascript:’’"id="__gwt_historyFrame"style="width:0;height:0;border:0"></iframe>

Notez que si vous n’utilisez pas le mécanisme d’historique, la présence de ce codeest inoffensive.

Ensuite, pour faire jouer le mécanisme :

• Lorsque l’application veut créer un point de sauvegarde, elle construit un jetond’historique contenant une représentation de son état, et appelle la méthodestatique History.newItem(token) où token est le jeton historique.

• Pour réagir à un changement d’état correspondant à un appui sur précé-dent ou suivant, voire même à l’ouverture directe d’un lien contenant unjeton d’historique, l’application doit déclarer un handler en appelant His-

tory.addValueChangeHandler(). Lorsqu’il est invoqué, le handler doit parserle jeton d’historique et rétablir l’état de l’application correspondant.

8.3 UN EXEMPLE

Nous allons illustrer le mécanisme d’historique avec un exemple dont le listingcomplet est accessible en annexe 4. On suppose qu’on a une application structuréesous forme d’une arborescence d’écrans ; la sélection d’un écran se fait par la sélectiond’un nœud dans un arbre GWT (Tree).

On décide que chaque changement d’écran, c’est-à-dire chaque clic sur unnœud de l’arbre, doit ajouter une entrée dans l’historique du navigateur. Onsuppose que l’état de l’application se résume à l’écran courant ; par conséquenton choisit de représenter l’état de l’application (et donc le token historique) parun identifiant du nœud sélectionné.

Pour simplifier ici, on utilisera le hashcode du texte du nœud comme identifiant,mais dans une application réelle, il faudrait utiliser un identifiant plus fiable, parexemple la classe implémentant l’écran correspondant. L’avantage de notre solutionest de fonctionner avec n’importe quel Tree.

8.3.1 Créer une entrée dans l’historique

La première partie de l’implémentation consiste en créer une entrée d’historique lorsde l’activation d’un écran ; on va donc effectuer cette action lors de la sélection d’unnœud dans l’arbre, grâce à un SelectionHandler.

Page 132: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

118 Chapitre 8. Le mécanisme d’historique de GWT

//// ajout SelectionHandler//tree.addSelectionHandler(new SelectionHandler<TreeItem>() {

public void onSelection(SelectionEvent<TreeItem> event) {// construire le token sur base du hashcode du texte// du noeud sélectionnéTreeItem selectedItem = event.getSelectedItem();String token = Long.toHexString(selectedItem.getText().hashCode());// créer une entrée d’historiqueHistory.newItem(token);

}});

Une fois le nœud sélectionné récupéré, on génère le token en convertissant en hexa-décimal le hashcode du texte du nœud, puis on appelle History.newItem avec ce token.

8.3.2 Réagir à un événement historique

La seconde partie de l’implémentation consiste en réagir à un événement historique,via un ValueChangeHandler :

//// ajout du handler historique//History.addValueChangeHandler(new ValueChangeHandler<String>() {

public void onValueChange(ValueChangeEvent<String> event) {// récupérer le tokenString token = event.getValue();// tenter de trouver le noeud corespondantTreeItem item = findNode(tree, token);if (item != null) {

// noeud trouvé: le sélectionnertree.setSelectedItem(item);// s’assurer que sa branche est déployéeensureExpanded(item);

}}

});

Le token reçu est récupéré de l’événement, ensuite on appelle une méthode maisonfindItem() qui parcourt l’arbre pour tenter de trouver le nœud dont l’identifiant(hashcode dans notre cas) correspond au token reçu. Si un tel nœud est trouvé, on lesélectionne et on s’assure qu’il est visible en déployant sa branche.

On peut vérifier en exécutant l’application qu’après avoir sélectionné plusieursnœuds à la suite, on peut utiliser les boutons Back et Forward du hosted mode pournaviguer dans l’historique ; avec à chaque fois la sélection du nœud correspondant.

On constate au passage qu’en hosted mode, la partie « fragment » de l’URL n’estpas mise à jour dans la barre d’adresse tant qu’on ne clique pas sur Refresh. C’est unpeu dommage car l’appui sur Refresh recharge l’application, ce qui n’est pas forcémentsouhaitable. En revanche, en mode web, on peut voir le fragment se mettre à jour àchaque fois que History.newItem() est appelé.

Page 133: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

8.4 Le widget Hyperlink 119

Figure 8.1 — Le jeton d’historique est visible dans la barre d’adresse en mode web

Dans cet exemple, le token n’est pas véritablement formaté, mais en pratique onpourra utiliser un encodage du type :

param1=val1;param2=val2...

Il convient d’être prudent lors du parsing d’un token, car il ne faut pas oublier quele token peut également provenir d’une URL qui a été saisie manuellement par unutilisateur directement dans la barre d’adresse.

8.4 LE WIDGET HYPERLINK

L’historique peut également être utilisé en conjonction avec un widget Hyperlink ;ce dernier crée un lien similaire à un lien web classique, mais il a pour effet dedéclencher l’activation d’un jeton d’historique à l’intérieur de l’application courante.Bien entendu, le jeton associé à l’Hyperlink doit être valide et pouvoir être parsécorrectement.

Page 134: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 135: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Envoyer des requêtes HTTP

9

ObjectifSi le mécanisme de RPC de GWT est idéal lorsqu’on maîtrise les deux côtés (client etserveur), il est des cas où on souhaite avoir plus de maîtrise sur les requêtes envoyéeset construire soi-même la requête HTTP. GWT le permet également au travers demodules dédiés.

9.1 AU­DELÀ DE GWT RPC

L’essentiel du chapitre 5 était centré sur GWT RPC, le mécanisme d’appels client-serveur préféré de GWT. Toutefois, il arrive qu’on ne puisse pas ou qu’on ne souhaitepas utiliser ce mécanisme ; c’est le cas par exemple si le backend ne permet pas dedéployer des servlets (par exemple, si on ne dispose que de PHP côté serveur), oubien si on souhaite accéder à des services existants et qui n’ont pas été développésspécifiquement pour un client GWT (par exemple des web services).

Dans ces différents cas, GWT permet tout de même de faire appel à ces services enoffrant des outils pour gérer manuellement l’envoi de requêtes HTTP personnalisées.De plus, GWT offre également des facilités pour encoder/décoder le contenu desmessages échangés au format JSON ou XML.

Page 136: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

122 Chapitre 9. Envoyer des requêtes HTTP

JSON et XML

JSON, acronyme de JavaScript Object Notation, est un format d’échange de données« allégé », simple à générer et à parser, communément utilisé pour le transport dedonnées sur un réseau. Il est notamment très répandu dans les applications AJAX, oùil constitue une alternative moins lourde à XML.Techniquement, JSON est une notation dérivée de JavaScript, ce qui le rend plus facileà manipuler dans ce langage ; cependant il est possible de manipuler JSON dans laplupart des langages actuels.Si en théorie un web service se doit de manipuler des messages SOAP (et donc XML),de plus en plus de web services publics (tel Google ou Yahoo) adoptent JSON commeformat de sortie.Tous les détails sur JSON se trouvent sur le site http://json.org.

9.2 REQUÊTES HTTP EN GWT

L’envoi de requêtes HTTP depuis le code GWT fonctionne globalement de façonsimilaire à n’importe quel langage, c’est-à-dire :

1. construction de la requête ;

2. envoi de la requête ;

3. traitement de la réponse.

Cependant, la nature de GWT implique certaines particularités qu’il faut garderen tête :

• comme pour les requêtes RPC, et pour les mêmes raisons, une requête HTTPest forcément asynchrone (voir § 5.2 Les principes RPC) ;

• les applications GWT étant exécutées à l’intérieur d’un navigateur web, tous lesaccès réseau sont soumis à la politique de sécurité du navigateur, en particulierla politique de même origine (Same Origin Policy ou SOP). En vertu de cettepolitique, le code exécuté dans le navigateur ne peut accéder à des ressourcesprovenant de serveurs autres que celui d’où a été chargée la page hôte. Cecicomplique l’accès à des ressources situées hors du serveur ; cependant, destechniques existent pour contourner cette limitation (voir § 9.5 Accès à desweb services JSON).

9.2.1 Réalisation d’un appel HTTP

Tout d’abord, si vous voulez effectuer des requêtes HTTP directement en GWT, vousdevrez hériter du module GWT « HTTP », ceci se fait simplement en ajoutant laligne suivante dans votre fichier module :

<inherits name="com.google.gwt.http.HTTP" />

Page 137: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

9.2 Requêtes HTTP en GWT 123

La réalisation d’un appel HTTP se fait alors comme suit :

1. on instancie un objet RequestBuilder en spécifiant la méthode (GET ou POST)et l’URL cible ;

2. optionnellement, on complète les paramètres de la requête en appelant :

– setUser() et setPassword() pour spécifier un nom d’utilisateur et un motde passe,

– setTimeoutMillis() pour spécifier une durée maximale d’attente de laréponse,

– setHeader() pour positionner des headers HTTP dans la requête ;

3. lorsque la requête est prête, on appelle sendRequest(String, RequestCall-

back), où le premier paramètre contient des données à passer à la requête, et lesecond est un callback destiné à traiter le résultat de l’appel ;

4. selon le résultat de l’appel :

– si l’appel a abouti et qu’une réponse a été reçue du serveur (même si celle-cine porte pas le code de succès HTTP 200), la méthode onResponseRecei-

ved(Request, Response) du callback est appelée. Le code de retour HTTP,les headers et le contenu de la réponse sont accessibles via les méthodes dela classe Response,

– si l’appel a échoué ou que la réponse n’a pas été reçue avant l’écoulement dela durée du timeout, la méthode onError(Request, Throwable) du callbackest appelée ; les causes de l’erreur sont contenues dans l’exception passéeen second paramètre.

Remarque

La méthode sendRequest() retourne un objet Request qui peut être utilisé pourinterroger le statut de la requête via isPending(), ou l’annuler via cancel().

On peut noter la similarité avec le mécanisme d’appel RPC ; en effet, ce n’est pasun hasard car le mécanisme RPC est construit sur la base du mécanisme de requêteHTTP.

Une fois la réponse reçue, son traitement est entièrement à la charge de l’appli-cation. Toutefois, si la réponse est encodée en XML ou JSON, GWT propose desbibliothèques dédiées à la manipulation de ces formats et qui faciliteront grandementla tâche.

Page 138: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

124 Chapitre 9. Envoyer des requêtes HTTP

9.3 MANIPULATION DE XML

XML est une part essentielle du Web et bien sûr de l’écosystème AJAX dont, rappelons-nous, il constitue le X... Sa standardisation, son interopérabilité, sa versatilité enont fait le format de prédilection pour de nombreux usages, depuis les fichiers deconfiguration jusqu’au transport de données pour les services réseau.

À la différence d’HTML qui s’attache à fournir la représentation des donnéesdans le but unique de les afficher dans un navigateur web, XML se concentre sur lasémantique des données, débarrassées de tout aspect de présentation. Par conséquent,XML doit être interprété et transformé pour être affiché ou autrement utilisé ; C’estdans ce but que GWT fournit une bibliothèque qui permet de parser un documentXML et de le parcourir sous forme d’arbre DOM, et inversement de créer un documentDOM et de le sérialiser sous forme de XML.

Les classes liées à la manipulation d’XML dans GWT se trouvent dans le packagecom.google.gwt.xml.client ; pour pouvoir les utiliser, il faut une fois de plus « héri-ter » du module GWT correspondant en ajoutant la ligne suivante au fichier deconfiguration du module :

<inherits name="com.google.gwt.xml.XML" />

9.3.1 Le DOM XML

DOM (Document Object Model) est en réalité une abstraction qui permet de mani-puler un document structuré sous forme arborescente au travers de ses composantsélémentaires. Cette abstraction s’applique à la structure d’une page web, mais aussi àun document XML.

Il faut noter que les classes de GWT qui manipulent le DOM XML sont totalementindépendantes de leurs homologues qui manipulent de DOM HTML ; les premièressont dans le package com.google.gwt.xml.client alors que les secondes sont dans lepackage com.google.gwt.dom.client. En outre, les types du DOM XML sont tous desinterfaces, alors que les types du DOM HTML sont des classes.

Le diagramme en figure 8.1 représente une vue partielle des types (interfaces) duDOM XML de GWT. Tous les types héritent de Node qui encapsule la relation parent-enfants. On y retrouve tous les constituants d’un document XML, essentiellementéléments et attributs.

9.3.2 Parsing d’un document XML

Le parsing d’un document XML se résume à l’appel de la méthode statique XMLPar-

ser.parse(String) en lui passant la chaîne contenant la représentation XML dudocument. Le résultat est un objet de type Document que l’on peut manipuler au traversd’une interface de type DOM.

L’objet Document ne possède qu’un seul fils qui est l’élément racine du documentXML ; on l’obtient avec la méthode getDocumentElement().

Page 139: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

9.3 Manipulation de XML 125

Figure 9.1 — Types du DOM XML

Pour naviguer dans l’arbre DOM, il existe plusieurs méthodes, selon la structuredu XML et ce que l’on cherche :

• Si on cherche à accéder à un élément désigné par un attribut de type ID, onpeut le retrouver directement en appelant getElementById() sur l’instance deDocument.

• Si on veut accéder à tous les éléments portant un nom donné, on utiliseragetElementsByTagName() qui retourne un objet de type NodeList permettantd’itérer sur la liste des éléments.

• Pour naviguer de proche en proche, on utilisera les méthodes getChildNodes(),getParentNode() et getNextSibling() qui donnent respectivement la liste desenfants directs (NodeList), le nœud parent, et le nœud collatéral suivant dansl’ordre de parcours de l’arbre.

Attention

Dans la première méthode, l’attribut doit être déclaré comme un ID au moyen d’unDocument Type Definition (DTD) associé au document XML ; il ne suffit pas d’appelerun attribut « id » pour en faire un ID au sens XML...

9.3.3 Création d’un document XML

La création d’un document XML sous forme d’arbre abstrait se fait grâce à la méthodestatique createDocument() de la classe XMLParser. On peut alors utiliser les méthodescreateXxxx() pour créer des nœuds (éléments, attributs, texte, etc.) et les « greffer »au document avec les méthodes appendChild() ou insertBefore().

Page 140: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

126 Chapitre 9. Envoyer des requêtes HTTP

Une fois le document créé et peuplé, on peut obtenir la représentation textuellede ce document (c’est-à-dire le code XML correspondant) en appelant la méthodetoString().

L’exemple suivant crée un document décrivant un flux Atom :

Document document = XMLParser.createDocument();Element feedElement = document.createElement("feed");feedElement.setAttribute("xmlns","http://www.w3.org/2005/Atom");

Element titleElement = document.createElement("title");titleElement.appendChild(document.createTextNode("Exemple"));feedElement.appendChild(titleElement);

Element linkElement = document.createElement("link");linkElement.setAttribute("href", "http://exemple.org");feedElement.appendChild(linkElement);

Element updatedElement = document.createElement("updated");updatedElement.appendChild(document.createTextNode("2009-12-13T18:30:02Z"));feedElement.appendChild(updatedElement);

Element authorElement = document.createElement("author");Element nameElement = document.createElement("name");nameElement.appendChild(document.createTextNode("Marcel Marceau"));authorElement.appendChild(nameElement);feedElement.appendChild(authorElement);

document.appendChild(feedElement);String xml = document.toString();

Le résultat (avec retours ligne ajoutés) :

<feed xmlns="http://www.w3.org/2005/Atom"><title>Exemple</title><link href="http://exemple.org"/><updated>2009-12-13T18:30:02Z</updated><author><name>Marcel Marceau</name></author></feed>

9.4 MANIPULATION DE JSON

Comme pour XML, la bibliothèque JSON de GWT est contenue dans un moduleséparé qu’il faut inclure en ajoutant la ligne suivante dans le fichier module :

<inherits name="com.google.gwt.json.JSON" />

Typiquement, une structure JSON est reçue sous forme de texte en réponse àune requête HTTP. De façon similaire à XML, cette chaîne doit être parsée pourêtre convertie en une structure qu’on peut explorer et manipuler ; c’est le rôle de laméthode statique parse() de le classe JSONParser. Cette méthode accepte une Stringet retourne un objet de type JSONValue.

Page 141: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

9.4 Manipulation de JSON 127

Figure 9.2 — Types JSON de GWT

La figure 8.2 présente la hiérarchie des types JSON de GWT. JSONValue est lasuperclasse abstraite de tous les types JSON ; pour savoir quel type est réellementreprésenté par un objet JSONValue, on peut utiliser une des méthodes isXxxx() quirenvoie une référence non nulle vers une instance du type Xxxx si et seulement si lavaleur représentée est du type Xxxx. Par exemple, isNumber() retourne un JSONNumber

si la JSONValue représente un JSONNumber, ou null dans le cas contraire. Bien sûr, sion connaît avec certitude le type concret de la JSONValue, on peut directement leconvertir via un cast.

La création d’un document JSON se fait de façon très simple en instanciantdirectement les classes JSON. Les types composites JSONObject et JSONArray sontremplis respectivement avec les méthodes put(String, JSONValue) et set(int,

JSONValue).

L’exemple suivant montre la création d’un document JSON :

JSONObject livre = new JSONObject();livre.put("Titre", new JSONString("GWT"));

JSONArray chapitres = new JSONArray();JSONObject chap1 = new JSONObject();chap1.put("Titre", new JSONString("Introduction"));chap1.put("Page", new JSONNumber(10));chapitres.set(0, chap1);

JSONObject chap2 = new JSONObject();chap2.put("Titre", new JSONString("Hello world"));chap2.put("Page", new JSONNumber(38));chapitres.set(1, chap2);

livre.put("Chapitres", chapitres);

String json = livre.toString();

Le résultat (avec retours ligne ajoutés) :

{"Titre":"GWT","Chapitres":[

{"Titre":"Introduction", "Page":10},{"Titre":"Hello world", "Page":38}]

}

Page 142: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

128 Chapitre 9. Envoyer des requêtes HTTP

9.5 ACCÈS À DES WEB SERVICES JSON

On l’a dit, l’envoi direct de requêtes HTTP depuis le code client GWT n’est possibleque vers le serveur d’où a été chargé ce code, à cause de la contrainte de sécurité « SameOrigin Policy » (SOP) imposée par les navigateurs. Ce problème n’affecte d’ailleurs pasque GWT mais toutes les applications AJAX.

Dès lors, comment faire pour accéder à un web service dont le serveur se trouven’importe où sur le Web ? Heureusement, une technique existe ; celle-ci consiste àinjecter dynamiquement (au travers de manipulations du DOM) un élément <SCRIPT>dont la source pointe vers l’URL du web service à appeler. Ce script étant insérédynamiquement, il n’est pas soumis à la contrainte SOP et peut donc accéder àn’importe quelle URL. Cependant, l’utilisation de cette technique n’est possible quesous certaines conditions.

• Étant donné que le résultat de la requête est utilisé comme source du scriptinjecté, celui-ci doit être du JavaScript. Fort heureusement, beaucoup de webservices peuvent retourner le résultat au format JSON, qui est lui-même unsous-ensemble de JavaScript. Par conséquent cette technique n’est utilisablequ’avec des web services capables de produire du JSON.

• Le web service doit également être capable de générer du code qui encapsulela réponse dans un appel à une fonction JavaScript arbitraire, pour pouvoirsignaler au code GWT qu’une réponse a été reçue. Cette variante de JSON estquelquefois appelée JSONP.

Pour faciliter la mise en œuvre de cette technique, on peut écrire une classeutilitaire JSONRequestHelper qui gère toute cette mécanique.

On va tout d’abord définir une interface JSONResponseHandler de type callback,que le code client devra implémenter pour recevoir la réponse. Pour la compacité, ona implémenté cette interface comme un type imbriqué de JSONRequestHandler :

public interface JSONResponseHandler {public void onResponseReceived(JavaScriptObject json);

}

On suppose qu’on fournira à notre classe utilitaire une URL à laquelle il resterajuste à concaténer le nom du callback JavaScript. L’appel au web service se fera enpassant cette URL incomplète et une instance de JSONResponseHandler à une méthodestatique :

/*** Effectue un appel à un web service JSON. Le web service doit* supporter les options "JSON in script" et "JavaScript callback".** @param url L’URL du service à appeler, moins le nom du callback.* Le nom du callback sera concaténé à la fin de l’URL; celle-ci* devra donc se terminer par un paramètre du type "callback=".* @param handler une instance de JSONResponseHandler dont* la méthode onResponseReceived

Page 143: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

9.5 Accès à des web services JSON 129

* sera appelée après réception du résultat.*/public static void get(String url, JSONResponseHandler handler) {

// Construire un nom de callback propre au handler.// Ceci permet de gérer des situations// où plusieurs appels simultanés sont faits// avec des handlers différents.String callbackName = "callback" + handler.hashCode();get(url + callbackName, callbackName, handler);

}

Le cœur de cette classe est constitué par une méthode native JSNI (voir § 7.1 JSNI(JavaScript Native interface)) :

/*** Méthode native JSNI qui effectue la manipulation du DOM.* @param url L’URL complète (y compris le callback)* @param callbackName Le nom du callback* @param handler Le handler client à appeler*/private native static void get(String url, String callbackName,

JSONResponseHandler handler) /*-{callback = function(j) {

[email protected]$JSONResponseHandler::onResponseReceived(Lcom/google/gwt/core/client/JavaScriptObject;)(j);

};$wnd[callbackName] = callback;

var script = $wnd.document.createElement("script");script.setAttribute("type", "text/javascript");script.setAttribute("src", url);$wnd.document.getElementsByTagName("head")[0].appendChild(script);

}-*/;

Quelques mots d’explication : cette méthode commence par enregistrer unefonction portant le nom du callback passé en paramètre, et qui se contente d’appelerle handler spécifié. Ensuite, on insère l’élément SCRIPT avec l’URL spécifiée commesource ; ceci déclenche l’envoi d’une requête HTTP. Lorsque le résultat est reçu, il estinterprété comme du JavaScript qui doit déclencher l’appel à la fonction de callback(pourvu que le serveur honore la convention JSONP), puis à notre handler client.Ouf !

L’appel lui-même se résume à ceci :

JSONRequestHelper.get(url, new JSONResponseHandler() {public void onResponseReceived(JavaScriptObject json) {

// Faire quelque chose avec l’objet reçu.// En general il s’agit d’un flux JSON qu’on peut// convertir en JSONObject pour le manipuler.JSONObject jsonValue = new JSONObject(json);// Traiter l’objet jsonValue...

}});

Le code complet de la classe JSONRequestHelper est accessible en annexe 5.

Page 144: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

130 Chapitre 9. Envoyer des requêtes HTTP

Attention

Cette classe est à considérer comme une preuve de concept, mais en aucun cas commeune classe de production ; en particulier les scripts insérés ne sont pas nettoyés aprèsusage, ce qui risque de provoquer des fuites de mémoire en cas d’usage intense.

Pour illustrer l’utilisation de cette classe, nous allons créer une petite applicationqui accède à un web service compatible. L’interface permettra de saisir l’URL duservice à appeler, un bouton Envoyer effectuera l’appel, et affichera le résultat dansune TextArea (figure 8.3).

Figure 9.3 — Interface utilisateur du client de test JSONP

Le code de la page HTML hôte et le code client sont accessibles en annexe 5.

Par défaut, nous allons utiliser un web service des API Google GData ; celui-cisupporte le format de résultat nécessaire grâce aux paramètres de la requête alt=json-

in-script et callback=xxx. L’URL qu’on va utiliser sera :

http://www.google.com/calendar/feeds/[email protected]/public/full?alt=json-in-script&callback=

On voit que la valeur du paramètre callback n’est pas renseignée ; c’est normal carelle le sera par JSONRequestHelper.

Si on accepte l’URL par défaut et qu’on clique sur Envoyer, après quelques secondesle résultat doit apparaître dans la TextArea sous forme d’un flux JSON (figure 8.4).

Bien sûr, dans une application réelle, il faudrait interpréter le JSON reçu pour enfaire quelque chose d’utile, ceci au moyen des classes JSON dédiées à cet effet (voir§ 8.4 Manipulation de JSON).

Page 145: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

9.6 Proxy serveur 131

Figure 9.4 — Le flux JSON retourné

9.6 PROXY SERVEUR

La technique précédente fondée sur JSONP fonctionne effectivement, et selon leschoix d’architecture, elle peut s’avérer la seule option viable, en particulier s’il n’estpas possible ou souhaitable d’implémenter des services sur le serveur qui sert le codeGWT.

En revanche, si on a la possibilité d’implémenter un service, que ce soit via GWTRPC ou une autre technique, alors ce service peut jouer le rôle de proxy et dialogueravec tout serveur web, où qu’il soit. Les contraintes de la politique SOP ne s’appliquentplus puisque la requête n’émane pas du navigateur, mais du serveur d’applications, quiagit comme intermédiaire.

Page 146: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 147: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Créer ses propres widgets

10

ObjectifCe chapitre vous expliquera les différentes façons de créer un widget GWTspécifique.

Les widgets utilisables avec GWT ne se limitent heureusement pas au cataloguede widgets natifs ; GWT a en effet prévu la possibilité pour les développeurs etfournisseurs de solutions tierces de créer des widgets spécifiques.

Il existe différentes techniques pour y parvenir :

• sous-classer un widget existant ;• créer un widget composite grâce à la classe Composite ;• implémenter complètement un widget en Java ;• faire appel à JSNI pour implémenter tout ou partie d’un widget en JavaScript.

Nous allons détailler ces différentes techniques.

Page 148: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

134 Chapitre 10. Créer ses propres widgets

10.1 SOUS­CLASSER UN WIDGET EXISTANT

Lorsqu’on a affaire à une bibliothèque de composants objet, cette méthode estla plus naturelle : on utilise comme super-classe le widget qui ressemble le plusà ce qu’on veut implémenter, et on surcharge les méthodes adéquates pour obtenirle comportement voulu.

De fait, cette technique a déjà été mise en œuvre à plusieurs reprises dans lesexemples de code illustrant la description de certains widgets :

• dans la section consacrée au DialogBox du paragraphe § 4.2.2 Widgets simples ;• dans la section consacrée aux Grid et FlexTable du paragraphe § 4.2.3 Panels.

Cette technique fonctionne parfaitement, mais elle n’est pas recommandée parGoogle pour des raisons de performance, et aussi parce que la sous-classe peut ne passouhaiter exposer toutes les méthodes de la classe qu’elle étend. Ainsi, si vous créez unwidget sur base de la classe HorizontalPanel, vous allez exposer toutes les méthodesde HorizontalPanel, telles que add, insert, etc., ce qui n’est probablement pas ce quevous souhaitez. Il reste la possibilité de surcharger ces méthodes pour ne rien faire oulever une exception, mais cette solution est pour le moins peu élégante.

Pour ces raisons, GWT suggère de préférer la technique faisant usage de la classeComposite.

10.2 UTILISER LA CLASSE COMPOSITE

Un Composite est un widget particulier qui contient un autre widget et se comporteexactement comme ce widget. En général, le widget encapsulé est un panel, ce quipermet de créer des composants riches en combinant différents widgets.

Cette technique est d’ailleurs utilisée à plusieurs reprises dans GWT lui-même :

• TabPanel est un Composite qui combine un TabBar et un DeckPanel ;• SuggestBox est un Composite qui combine une TextBox et un MenuBar.

Il est au passage vivement conseillé de consulter le code source de ces classes pourmieux comprendre comment fonctionne un Composite ! C’est un des avantages del’Open Source pour les développeurs.

La création d’un widget grâce à la classe Composite est assez similaire au sous-classage, avec les différences présentées dans le tableau 10.1.

C’est l’appel à initWidget(Widget) qui spécifie au Composite quel est le widgetencapsulé.

Page 149: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

10.3 Implémenter complètement un widget en Java 135

Tableau 10.1 — Différences entre le sous­classage et la classe Composite

Sous­classage Utilisation de CompositeLa classe hérite de la classe de widgets W La classe hérite de Composite

La classe possède une variable de type W

Le constructeur fait appel au constructeurde W et initialise les sous­widgets

Le constructeur instancie W et le configure, puisappelle initWidget(w)

À titre d’exemple, on va implémenter un widget composite qui peut servir àsélectionner le sexe d’une personne au moyen de deux boutons radio. Avec l’approched’héritage direct, on pourrait créer une sous-classe de VerticalPanel, au risque d’ex-poser les méthodes de VerticalPanel. Il est donc préférable d’en faire un composite,dont le widget principal est un VerticalPanel :

public class SexeRadio extends Composite {private VerticalPanel panel;private RadioButton rbm;private RadioButton rbf;public SexeRadio() {

panel = new VerticalPanel();rbm = new RadioButton("sexerb", "M");rbf = new RadioButton("sexerb", "F");panel.add(rbm);panel.add(rbf);initWidget(panel);

}public boolean isM() {

return rbm.getValue();}public boolean isF() {

return rbf.getValue();}

}

On peut ensuite l’instancier et l’utiliser comme n’importe quel widget. Les seulesméthodes exposées par ce widget, outre celles de Composite, sont les méthodes isM()et isF() qui permettent de savoir quelle case a été cochée.

10.3 IMPLÉMENTER COMPLÈTEMENT UN WIDGETEN JAVA

Plutôt que d’implémenter un widget par héritage ou composition de widgets existants,on peut s’attaquer à la création d’un widget personnalisé à un niveau d’abstractionen dessous, c’est-à-dire en manipulant directement le DOM. Bon nombre de widgetsde base du catalogue GWT sont écrits de cette manière, comme Button ou TextBox,en s’appuyant sur des composants HTML natifs. De nouveau, nous vous invitonsà consulter le code source de ces widgets si vous souhaitez voir comment ils sontimplémentés.

Page 150: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

136 Chapitre 10. Créer ses propres widgets

La manipulation du DOM se fait au travers de classes GWT spécialement prévuesà cet effet :

• Document est la classe principale ; elle encapsule toute la hiérarchie HTMLde la page et fournit en outre une flopée de méthodes utilitaires pour créerdes éléments HTML et événements, et obtenir des informations sur la page.On obtient l’instance courante de Document en appelant la méthode statiqueDocument.get().

• Element est la classe de base de tous les éléments ; il existe une sous-classecorrespondant à chacun des types d’éléments HTML, par exemple ButtonE-

lement représente un élément <button>, InputElement représente un élément<input>, etc. Pour créer un Element, on appellera la méthode correspondante deDocument, par exemple createButtonElement() pour créer un ButtonElement.

Voici par exemple comment est implémenté le constructeur de Button dans le codesource de GWT :

/*** Creates a button with no caption.*/public Button() {

super(Document.get().createPushButtonElement());setStyleName("gwt-Button");

}

On voit que le Button de GWT s’appuie totalement sur l’élément HTML corres-pondant, obtenu par l’appel à createPushButtonElement(). Ceci illustre une politiquede GWT qui est de s’appuyer sur les contrôles HTM natifs lorsque c’est possible.

10.4 IMPLÉMENTER TOUT OU PARTIE D’UN WIDGETEN JAVASCRIPT

En dernier recours, il est aussi possible d’utiliser JSNI (voir § 7.1 JSNI (JavaScriptNative Interface)) pour écrire tout ou partie de l’implémentation d’un widget personna-lisé en JavaScript. Cependant, si on choisit cette méthode, il faut être conscient despoints suivants (qui sont valables de façon générique pour toute utilisation de JSNI) :

• les différences éventuelles de comportement entre les différentes plates-formescibles ne sont plus prises en charge par GWT. En cas de divergence d’unnavigateur à l’autre, ce sera à vous de prendre vos précautions pour assurerun comportement homogène ;

• vous ne bénéficierez plus des contrôles statiques du compilateur Java, etd’éventuels problèmes dans le code JavaScript imbriqué ne seront détectés quelors de l’exécution de ce code ;

• le débogage en sera d’autant plus compliqué.

Page 151: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

10.4 Implémenter tout ou partie d’un widget en JavaScript 137

Lorsque vous choisissez d’utiliser cette méthode, il est conseillé de regrouperles méthodes faisant appel à JSNI dans une classe instanciée par Deferred Binding(voir § 7.2 Deferred Binding), c’est-à-dire au travers de GWT.create(), et non par uneréférence directe. Ceci permettra, le cas échéant, de fournir une version différente decette classe en fonction de la plate-forme.

Page 152: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 153: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Bibliothèques tierces

11

ObjectifEn donnant la possibilité de créer ses propres widgets, les créateurs de GWT ontpermis l’apparition de bibliothèques de composants qui complètent ou remplacent leswidgets de base. Néanmoins, les bibliothèques tierces ne se limitent pas aux aspectsd’IHM, et de véritables frameworks basés sur GWT ont vu le jour.Ce chapitre a pour objectif de présenter les principales d’entres elles.

11.1 BIBLIOTHÈQUES DE COMPOSANTS

11.1.1 GWT­ext

Ceux d’entre vous qui ont déjà pratiqué la programmation JavaScript connaissentpeut-être « Ext JS » (autrefois appelé simplement « Ext ») : il s’agit d’une bibliothèqueJavaScript articulée autour d’une palette de composants graphiques riches et flexibles,par exemple : des grilles incluant le filtrage et le tri, la possibilité de réordonner lescolonnes, le support de la pagination, les combo boxes, les barres d’outils, etc. Ext JS estdestiné au départ à la création d’applications RIA « à l’ancienne » c’est-à-dire codéesdirectement en JavaScript.

GWT-ext est un projet qui vise à permettre l’utilisation des composants ExtJS dans une application GWT ; pour cela, GWT-ext met à profit la possibilitéofferte par GWT d’implémenter une fonction en JavaScript natif grâce à JSNI.GWT-ext constitue donc un « wrapper » ou adaptateur, qui expose une interfaceJava/GWT pour les fonctionnalités de Ext JS. La présence de la bibliothèqueExt JS est cependant toujours requise, puisque les appels aux méthodes de GWT-Extsont en réalité convertis en appels Ext JS.

Page 154: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

140 Chapitre 11. Bibliothèques tierces

GWT-Ext souffre toutefois d’un handicap important : en effet, suite à un change-ment de la licence accompagnant Ext JS depuis la version 2.1, GWT-Ext ne peut plusutiliser de version de Ext JS postérieure à la version 2.0.2. Cependant, malgré cela,GWT-Ext offre une richesse et une maturité inégalées, c’est pourquoi elle reste uneoption viable pour une nouvelle application GWT ; il suffit de voir le « showcase » quiprésente tous les composants pour s’en convaincre : http://www.gwt-ext.com/demo.

La dernière version de GWT-Ext est 2.0.6, qu’on peut trouver sur la page suivante(avec un lien pour télécharger Ext JS 2.0.2) : http://code.google.com/p/gwt-ext.

À noter que le développeur principal de GWT-Ext, Sanjiv Jivan, travaille désor-mais sur une autre bibliothèque, SmartGWT, que nous évoquerons plus loin.

Installation

L’installation de GWT-Ext est assez mal documentée sur le Web, mais si vous suivezattentivement les étapes ci-après, cela ne posera pas de problèmes. En raison de sanature, l’installation se passe en deux étapes :

1. installation de la bibliothèque JavaScript Ext JS ;

2. installation de la bibliothèque et du module GWT-ext.

Étape 1 : Installer Ext JS1. Téléchargez Ext JS 2.0.2 depuis la page citée plus haut. Vous devriez obtenir

un fichier ext-2.0.2.zip.

2. Décompressez ce fichier dans un dossier temporaire. Vous devriez obtenir lesfichiers présentés en figure 11.1.

Figure 11.1 — Contenu de l’archive EXT JS

3. Dans le dossier war de votre projet GWT, créez un dossier js puis un sous-dossierext.

Page 155: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 141

4. Copiez les dossiers et fichiers suivants depuis l’endroit où vous avez décompressél’archive Ext-JS vers le dossier js/ext que vous venez de créer :

– adapter/

– resources/

– ext-all.js

– ext-all-debug.js

– ext-core.js

– ext-core-debug.js

5. Après l’opération, rafraîchissez le projet dans Eclipse (clic droit puis Refresh)pour prendre en compte les nouveaux fichiers. Dans la vue Navigator d’Eclipse,le projet doit avoir la structure présentée en figure 11.2.

Figure 11.2 — Structure du projet pour Ext JS

Étape 2 : Installer GWT-Ext1. Téléchargez la dernière version de GWT-Ext depuis la page citée plus haut.

Vous devriez obtenir un fichier gwtext-2.0.x.zip.

2. Décompressez ce fichier dans un dossier temporaire. Vous devriez obtenir lesfichiers présentés en figure 11.3.

Figure 11.3 — Contenu de l’archive GWT­Ext

Page 156: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

142 Chapitre 11. Bibliothèques tierces

3. Copiez le fichier gwtext.jar dans le dossier war/WEB-INF/lib de votre projet.

4. Après l’opération, rafraîchissez le projet dans Eclipse (clic droit puis Refresh)pour prendre en compte le nouveau fichier. Dans la vue Navigator d’Eclipse, leprojet doit avoir la structure présenté en figure 11.4.

Figure 11.4 — Structure du projet pour GWT­Ext

5. Ajoutez le nouveau JAR dans le build path du projet :

– clic droit sur le projet puis Properties ;– sélectionnez dans la liste de gauche la catégorie Java Build Path ;– sélectionnez l’onglet Libraries ;– cliquez sur Add JARs... ;– dans la fenêtre de sélection qui s’ouvre, sélectionnez le fichier JAR que vous

venez d’ajouter à votre projet (figure 11.5).

Figure 11.5 — Sélection du JAR gwtext.jar

Page 157: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 143

Au final, le build path devra être comme sur la figure 11.6.

Figure 11.6 — Build path final pour GWT­Ext

6. Modifiez le fichier module du projet pour y ajouter les lignes suivantes :

<!-- Inclure le module GWT-ext --><inherits name=’com.gwtext.GwtExt’ /><!-- Inclure le CSS et le code Ext JS --><stylesheet src="/js/ext/resources/css/ext-all.css" /><script src="/js/ext/adapter/ext/ext-base.js" /><script src="/js/ext/ext-all.js" />

Voilà, le projet est prêt pour développer avec GWT-ext !

Utilisation

GWT-Ext introduit une hiérarchie de widgets parallèle à celle de GWT. DansGWT, tous les composants héritent de la classe Widget, et les composants quipeuvent contenir d’autres éléments héritent de la classe Panel. Par contraste, tousles composants de GWT-Ext héritent de la classe Component, et ceux qui peuventcontenir d’autres composants héritent de la classe Container.

Fort heureusement, Component est lui-même une sous-classe de Widget, ce quipermet de faire cohabiter des éléments de GWT-Ext et des éléments natifs de GWT.Cependant, la richesse des composants GWT-Ext rend cela sans intérêt.

Le composant central de GWT-Ext est Panel ; il s’agit d’un composant trèsversatile qui peut aussi bien être un simple conteneur pour gérer la disposition d’autrescomposants, que contenir une barre d’outils, des sections d’entête et de pied, etc.

Page 158: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

144 Chapitre 11. Bibliothèques tierces

L’exemple suivant crée deux panels « collapsibles » (réductibles) côte à côte.

package oge.gwt.chap1111.client;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.ui.RootPanel;import com.gwtext.client.widgets.Panel;import com.gwtext.client.widgets.layout.HorizontalLayout;

/*** Entry point classes define <code>onModuleLoad()</code>.*/public class GwtChap1111 implements EntryPoint {

private static final String HTML_TEXT ="<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "

+ "Sed metus nibh, sodales a, porta at, vulputate eget, dui. "+ "In pellentesque nisl non sem. Suspendisse nunc sem, pretium eget, "+ "cursus a, fringilla vel, urna.";/*** Point d’entrée*/

public void onModuleLoad() {Panel main = new Panel();main.setLayout(new HorizontalLayout(15));main.setPaddings(15);Panel panel = new Panel();panel.setTitle("Panel 1");panel.setWidth(200);panel.setCollapsible(true);panel.setHtml(HTML_TEXT);main.add(panel);Panel panel2 = new Panel();panel2.setTitle("Panel 2");panel2.setWidth(300);panel2.setCollapsible(true);panel2.setHtml(HTML_TEXT);main.add(panel2);RootPanel.get().add(main);

}}

On voit qu’il est très aisé de créer des interfaces complexes, et avec un résultatgraphique intéressant et en tout cas plus évolué que GWT de base (figure 11.7).

Une différence importante avec GWT est la façon de gérer la disposition (layout)des sous-widgets. En effet, alors que les panels de GWT sont spécifiquement dédiés àun type de disposition (HorizontalPanel, VerticalPanel, FlexGrid, etc.), au contrairedans GWT-Ext, un conteneur n’impose pas par lui-même de disposition de sescomposants-fils, et on peut lui affecter un type de disposition au moyen de la méthodesetLayout(ContainerLayout).

En fonction de cette disposition, il est ensuite possible d’ajouter des contraintesspécifiques à un des fils au moment de son ajout, en passant un paramètre supplé-mentaire de type LayoutData à la méthode add(Component) de la classe Container. Laclasse concrète de l’instance de LayoutData doit correspondre au layout du conteneur ;par exemple, si on affecte à un panel le layout BorderLayout, c’est une instance de

Page 159: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 145

BorderLayoutData qu’il faudra passer à la méthode add. Ce pattern de conception seretrouve dans d’autres bibliothèques d’interface utilisateur, comme Swing.

Figure 11.7 — Exemple d’interface créée avec GWT­Ext

Pour aller plus loin

GWT-Ext hérite de toute la richesse de Ext-JS, ce qui en fait une bibliothèquerelativement complexe qu’il est impossible de décrire complètement dans ce livre.Malheureusement, la documentation est assez disparate et parfois lacunaire. Par contre,chacun des exemples du showcase (dont on a donné l’adresse plus haut) est accompagnédu code source Java correspondant, ce qui constitue une ressource précieuse !

Il existe aussi un forum (anglophone) à l’adresse http://gwt-ext.com/forum.

11.1.2 Ext­GWT

En parallèle au développement de Ext JS, une bibliothèque nommée MyGWT a vu lejour. Son but était simple : reprendre toutes les caractéristiques qui ont fait le succèsde Ext JS, y compris le look & feel des composants, mais en Java/GWT pur, c’est-à-diresans utiliser Ext JS (contrairement à GWT-ext).

MyGWT a été renommé Ext-GWT en 2008, et intégré au portfolio de la sociétéExt. Si l’objectif visé est sans doute d’homogénéiser les noms des produits de la gamme(« Ext JS » et « Ext GWT »), cela n’est pas sans créer une certaine confusion avecla bibliothèque GWT-Ext. Pour éviter (ou ajouter à) cette confusion, Ext-GWT estparfois aussi appelé GXT.

Fonctionnellement, Ext-GWT présente de nombreuses nouveautés par rapport àGWT-Ext ; on peut citer entre autres :

• une API de génération de graphiques (qui s’appuie sur flash) ;• le « data binding » c’est-à-dire la possibilité de lier directement les champs d’un

formulaire aux propriétés d’un objet ;• un éditeur HTML intégré.

Page 160: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

146 Chapitre 11. Bibliothèques tierces

Tableau 11.1 — Différences entre les deux bibliothèques Ext­GWT et GWT­Ext

Ext­GWT = GXT

(anciennement MyGWT)

GWT­Ext

Type Bibliothèque 100 % Java/GWT Wrapper JavaScript

Dernière version 2.0.1 2.0.6

Prérequis GWT 1.6+ GWT 1.5.3+, Ext JS 2.0.2

Licence au choix : GPL v3 oucommerciale

LGPL

Développeur/éditeur Darrel Meyer / Ext Sanjiv Jivan & autres

Site web http://extjs.com/products/gxt http://gwt­ext.com,http://code.google.com/p/gwt­ext

Installation

GWT-Ext étant « stand-alone » (il ne dépend pas d’une bibliothèque externe JavaS-cript), son installation est beaucoup plus simple que celle de GWT-ext.

1. Téléchargez « Ext GWT 2.0.x SDK » (dernière version) depuis la pagehttp://extjs.com/products/gxt/download.php. Vous devriez obtenir un fichiergxt-2.0.x.zip.

2. Décompressez ce fichier dans un dossier temporaire. Vous devriez obtenir lesfichiers présentés en figure 11.8.

Figure 11.8 — Contenu de l’archive GXT

3. Copiez le fichier gxt.jar dans le dossier war/WEB-INF/lib de votre projet.

4. Copiez tous les dossiers contenus dans le sous-dossier resources vers le dossierwar de votre projet. Les dossiers concernés sont :

– charts/

– css/

– desktop/

– flash/

– images/

– themes/

Page 161: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 147

5. Après l’opération, rafraîchissez le projet dans Eclipse (clic droit puis Refresh)pour prendre en compte les nouveaux fichiers. Dans la vue Navigator d’Eclipse,le projet doit avoir la structure présenté en figure 11.9.

Figure 11.9 — Structure du projet pour GXT

6. Ajoutez le nouveau JAR dans le build path du projet :

– clic droit sur le projet puis Properties ;– sélectionnez dans la liste de gauche la catégorie Java Build Path ;– sélectionnez l’onglet Libraries ;– cliquez sur Add JARs... ;– dans la fenêtre de sélection qui s’ouvre, sélectionnez le fichier JAR que vous

venez d’ajouter à votre projet (figure 11.10).

Figure 11.10 — Sélection de l’archive JAR gxt.jar

Page 162: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

148 Chapitre 11. Bibliothèques tierces

Au final le build path devra être comme présenté sur la figure 11.11.

Figure 11.11 — Build path final pour GXT

7. Modifiez le fichier module du projet pour y ajouter les lignes suivantes :

<!-- Inclure le module Ext GWT --><inherits name=’com.extjs.gxt.ui.GXT’/><!-- Inclure la feuille de style --><stylesheet src="/css/gxt-all.css" />

Utilisation

Bien que réécrite en GWT/Java sans l’aide de Ext-JS, Ext-GWT montre clairementson lien de parenté avec Ext-JS ; en effet on retrouve beaucoup de similitudes avecGWT-Ext. Ainsi la classe ContentPanel est le pendant de la classe Panel de GWT-Ext.

On retrouve aussi dans Ext-GWT une classification des widgets similaire :

• tous les widgets de Ext-GWT sont des sous-classes de Component ;• les composants pouvant avoir des composants-fils sont des sous-classes de

Container.

Une autre similitude est la gestion des layouts : comme pour GWT-Ext, on associeun Layout au conteneur, et on ajoute les composants-fils en passant un LayoutData

approprié à la méthode add.

Ext-GWT offre en outre une possibilité intéressante de lier directement les champsd’un formulaire aux propriétés d’un objet ; c’est ce qu’on appelle le « data binding ». Decette manière, par le jeu de listeners et de convertisseurs, le changement d’une valeurdans un champ entraîne immédiatement la mise à jour de la propriété correspondantede l’objet ; inversement, un changement dans la valeur d’une propriété entraînera lamise à jour du champ qui lui est lié.

Malheureusement, étant donné l’impossibilité de faire de l’introspection en GWT,le data binding n’est pas possible avec n’importe quel Java Bean, mais seulement avec

Page 163: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 149

un type de modèle spécifique à Ext-GWT (BaseModel) dans lequel les propriétés sontstockées sous forme de Map.

Ext-GWT contient aussi un embryon de framework MVC (Model-View-Controller),ou qui se dit comme tel ; cependant il possède de nombreux vices de conception quile rendent difficile à utiliser, et il est souhaitable de s’en passer au profit d’un autreframework MVC tel PureMVC, ou d’un développement propre.

Pour aller plus loin

Contrairement à GWT-Ext qui est sous licence LGPL, Ext-GWT est disponible soitsous licence GPL, ce qui oblige tout logiciel l’utilisant à être lui-même disponible sousGPL, soit avec une licence commerciale donnant droit à un support préférentiel. Celapeut influer fortement sur le choix d’une bibliothèque.

Ext-GWT est un peu mieux documenté que GWT-Ext, mais contrairement àl’affirmation du site web, son code source est encore loin d’être « bien conçu,cohérent et entièrement documenté ». La principale source de documentationreste le showcase, qui donne également accès au code source des exemples :http://www.extjs.com/examples.

Un forum est également ouvert, mais attention, certaines sections dédiées ausupport préférentiel ne sont accessibles qu’aux titulaires d’une licence commerciale :http://www.extjs.com/forum.

11.1.3 SmartGWT

SmartGWT est le nouveau projet de Sanjiv Jivan, le créateur de GWT-Ext ; ils’agit là aussi d’un wrapper, cette fois pour la partie « client AJAX » de SmartClient(http://www.smartclient.com), un framework complet de développement qui offre nonseulement des composants pour la réalisation de l’interface utilisateur, mais en outrepermet de lier ces widgets avec les données côté serveur.

Même si SmartClient est conçu pour être une solution de bout en bout (du serveurau poste client), SmartGWT peut cependant être utilisé comme une solution « clientseulement ».

SmartGWT, tout comme l’ensemble de SmartClient, est disponible avec plusieursoptions de licence, dont la licence LGPL. Ceci le met en bonne position par rapportà GWT-Ext (dont le développement se limite désormais à la correction de bugs), etExt-GWT (qui n’est pas disponible sous licence LGPL).

SmartGWT est hébergé sur Google Code et peut être téléchargé depuis lapage suivante : http://code.google.com/p/smartgwt/

11.1.4 Autres composants

En plus des bibliothèques décrites ci-avant, GWT a donné naissance à une myriadede projets plus petits, moins aboutis ou moins cohérents que celles-ci. Nous allons enciter quelques uns qui présentent un intérêt particulier.

Page 164: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

150 Chapitre 11. Bibliothèques tierces

GWT Incubator

GWT Incubator n’est pas un projet à proprement parler, mais plutôt l’endroit où sontdéveloppées les futures extensions de GWT, widgets ou bibliothèques, avant qu’ellessoient intégrées au toolkit de base (pour celles qui le seront).

GWT Incubator contient à ce jour les fonctionnalités suivantes :

• catégorie « widgets » :

– ScrollTable, une table scrollable avec un entête et un pied fixes,

– PagingScrollTable, une table scrollable et paginée,

– Bulk table renderers, des utilitaires permettant d’optimiser l’affichage destables en effectuant le rendu en une seule opération pour toute la table (aulieu de cellule par cellule),

– CollapsiblePanel, un panel affichable quand la souris suvole une zone,

– GlassPanel, qui permet de griser/coloriser un panel,

– FastTree, un arbre optimisé pour gérer efficacement un grand nombre denœuds,

– SliderBar, un widget qui permet de faire une sélection grâce à un curseur(slider),

– Spinner, un widget qui permet d’incrémenter/décrémenter la valeur d’unchamp grâce à un paire de boutons,

– DropDownListBox, un équivalent de ListBox mais qui facilite l’applicationdes styles,

– ProgressBar, un classique indicateur de progrès,

– SimpleWidget, une façon de créer un widget très facilement ;

• catégorie « bibliothèques » :

– une bibliothèque de validation pour la validation côté client,

– une bibliothèque permettant de faire du logging côté client,

– GWTCanvas, une bibliothèque qui permet de faire du dessin vectoriel dans lenavigateur ;

• catégorie « utilitaires » :

– Decorator, qui permet de décorer des widgets en leur ajoutant des élémentsHTML spécifiques,

– CssResource/StyleInjector, qui permet d’améliorer la gestion des feuillesde style CSS en les rendant extensibles, modulaires, internationalisables,injectables et manipulables dynamiquement, etc. Ce sous-projet est d’oreset déjà planifié pour faire partie de la prochaine version de GWT (2.0),

– SoundRessource, qui permet de gérer les sons (nécessite le plugin Flash),

– LocalListLister, qui permettent d’obtenir dynamiquement la liste delocales compilées dans un projet afin d’offrir un choix à l’utilisateur.

Page 165: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.1 Bibliothèques de composants 151

GWT Component Library

GWT component Library est une collection de widgets divers qui répondent à desbesoins spécifiques sans cohérence particulière.

Ces widgets ont pour la plupart un caractère expérimental et ne sont donc pasrecommandés pour une application destinée à la production... ou alors, à vos risques etpérils. En outre, certains d’entre eux sont devenus obsolètes puisque leur fonctionnalitéa été depuis intégrée à GWT (Auto-Completion Textbox > SuggestBox, Simple XML

Parser > XMLParser).

On trouve ces composants sur la page suivante :

http://gwt.components.googlepages.com.

GWT Widget Library

GWT Widget Library est la partie « widgets » d’une bibliothèque qui comprendégalement des classes destinées à faciliter l’implémentation de services RPC (côtéserveur) appelée GWT Server Library.

On y trouve également un certain nombre de widgets originaux comme unecalculatrice popup (PopupCalcPanel), un label texte qui se transforme en champéditable lorsqu’on clique dessus (EditableLabel), etc.

Malheureusement, la documentation se limite à la JavaDoc et aucun showcase pouravoir un aperçu visuel...

Téléchargement : http://gwt-widget.sourceforge.net.

GWTiger

GWTiger est un framework léger bâti sur GWT qui apporte les fonctionnalitéssuivantes :

• champs pour formulaires incluant label et gestion d’un éventuel messaged’erreur ;

• validation ;• contrôles de saisie selon un masque ;• lazy loading ou instanciation tardive, permettant de ne construire un écran que

lorsqu’on en a besoin ;• écran de login ;• support automatique du bouton back.

Site web : http://gwtiger.org.

Page 166: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

152 Chapitre 11. Bibliothèques tierces

11.2 BIBLIOTHÈQUES UTILITAIRES

11.2.1 Gwittir

Gwittir au nom imprononçable est un ensemble très cohérent de classes utilitairespour GWT qui se concentre sur des fonctionnalités manquantes, telles que :

• le binding, c’est-à-dire la possibilité de lier un composant graphique avec unmodèle, de sorte que tout changement sur l’un mette à jour l’autre ;

• la validation, afin de vérifier la validité du modèle et de fournir un feedback àl’utilisateur en cas d’erreur ;

• une implémentation minimale de l’introspection qui permet d’interroger uneclasse pour en connaître les propriétés ;

• le support des raccourcis clavier ;• une API extensible de logging côté client ;• la gestion d’un flux applicatif (c’est-à-dire un enchaînement d’écrans) avec

support du mécanisme d’historique de GWT ;• une possibilité de streaming via RPC, c’est-à-dire la possibilité pour le serveur de

retourner un volume important de données en plusieurs fois, le tout étant géréde façon transparente pour l’utilisateur.

Gwittir est documenté de façon succincte mais efficace dans le wiki du projet, quiest hébergé sur google projets : http://code.google.com/p/gwittir/

11.2.2 GWT Server Library

GWT Server Library est la partie « serveur » qui fait le pendant de GWT WidgetLibrary déjà mentionné plus haut. GWT-SL est principalement axé sur l’intégrationde services GWT-RPC avec Spring sur le serveur.

En particulier, GWT-SL permet de publier sous forme de services RPC pour GWTcertaines méthodes d’un POJO (Plain Old Java Object, c’est-à-dire un objet Java surlequel on n’impose pas de contrainte spécifique). L’implémentation du service n’a parconséquent aucune dépendance envers GWT.

GWT-SL permet aussi de mapper rapidement une URL avec un service RPC viala configuration d’un bean (GWTHandler).

La documentation est concise mais complète, et se trouve avec les téléchargementssur la page suivante : http://gwt-widget.sourceforge.net.

11.2.3 Google API

Indépendamment de GWT, Google propose aux développeurs JavaScript sous le nomde « Google API » un certain nombre de bibliothèques permettant d’enrichir lesapplications AJAX de fonctionnalités additionnelles, la plupart du temps en relationavec des services en ligne de Google. Avec l’apparition de GWT, ces bibliothèques

Page 167: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.2 Bibliothèques utilitaires 153

ont été portées pour GWT sous le nom de « Google API Libraries for GoogleWeb Toolkit », et permettent désormais de bénéficier des mêmes services que leurshomologues JavaScript, directement en Java.

Les différentes API sont les suivantes :

• Gears permet de fournir des fonctionnalités locales aux applications qui s’exé-cutent dans le navigateur, comme la sauvegarde de données sur le poste client,des tâches d’arrière plan, etc. Cette API peut s’avérer essentielle dans le cadred’une application GWT, car elle peut faciliter l’implémentation d’un mode« offline » lorsque le serveur n’est pas disponible par exemple ;

• Gadgets facilite la création avec GWT de « gadgets », ces mini-applicationsqu’on peut intégrer dans des pages web (comme la page d’accueil personnaliséede igoogle.com) ;

• Search permet l’intégration de la recherche Google dans une application GWT ;• Visualization permet de générer des représentations graphiques sous une

variété de formats tels que camemberts, timelines, cartes géographiques (toutesles visualisations ne sont pas encore gérées par l’API GWT) ;

• Language permet de fournir un accès aux fonctionnalités de traduction et detranslitération de Google Translate ;

• Maps permet d’intégrer des cartes fournies par Google Maps dans une applicationGWT.

Bien qu’elles fassent appel derrière les rideaux à des fonctions JavaScript, les APIGoogle pour GWT sont stand-alone et s’utilisent comme de simples bibliothèques Java.En outre, la Javadoc incluse est complète. Cependant, il est toujours préférable de sefamiliariser avec l’API originale, qui reste la référence.

Les API Google sont extrêmement riches, et leur étude n’entre pas dans le cadrede ce livre. Cependant, à titre d’illustration, nous allons utiliser l’API Gears dans lecadre d’un exemple.

Exemple d’utilisation de l’API Gears (Database)

Gears offre plusieurs fonctionnalités, parmi lesquelles :

• Database, une véritable base de données SQL locale ;• LocalServer, qui permet de cacher localement des ressources (pages HTML,

fichiers JavaScript, images, etc.) destinées à faciliter l’utilisation en modedéconnecté ;

• WorkerPool, qui permet de gérer des opérations en tâche de fond ;• la géolocalisation, pour trouver aussi précisément que possible la position

géographique.

Page 168: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

154 Chapitre 11. Bibliothèques tierces

Nous allons mettre en œuvre la partie « database », et créer une petite applicationGWT qui stockera localement des données.

Installation

L’ensemble des bibliothèques GWT pour les API Google se trouve sur la page suivante :http://code.google.com/p/gwt-google-apis.

L’installation de l’API Gears est aussi simple que possible :

1. téléchargez l’archive gwt-gears-1.2.x.zip depuis la page ci-dessus ;

2. décompressez l’archive dans un dossier temporaire. Celle-ci doit contenirplusieurs fichiers et dossiers, dont le JAR lui même et de la documentation ;

3. copiez le fichier gwt-gears.jar dans le dossier war/WEB-INF/lib de votre projetGWT ;

4. ajoutez ce fichier JAR au build path de votre projet (comme expliqué précédem-ment) ;

5. modifiez le fichier de module pour y inclure les lignes suivantes :

<!-- inclure le module Gears --><inherits name=’com.google.gwt.gears.Gears’/>

Utilisation

La base de données de Gears s’utilise au moyen d’un objet de type Database.

La séquence d’opérations est la suivante :

1. obtenir une instance de Database en faisant appel àFactory.getInstance().createDatabase() ;

2. ouvrir une base de données avec Database.open() ;

3. exécuter des ordres SQL sur la base au moyen de Database.execute().

La base de données de Gears utilise le moteur Open Source SQLite, qui possède sonpropre dialecte SQL. Le SQL de Gears est, à quelques variantes près, le même que celuide SQLite ; il est documenté sur la page suivante : http://www.sqlite.org/lang.html.

Nous allons utiliser une base locale pour stocker des messages que l’utilisateurentrera, associés à la date de leur saisie.

La création de la base se fait delà façon suivante :

// Créer la base si elle n’existe pastry {

db = Factory.getInstance().createDatabase();db.open("gears-database-demo");db.execute("create table if not exists demo (

Message text, Timestamp int)");} catch (GearsException e) {

Window.alert(e.toString());}

Page 169: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.2 Bibliothèques utilitaires 155

Ceci crée une base avec une table demo contenant deux colonnes. Pour y accéderen lecture, on utilisera une instruction select avec un code similaire à ce qui suit :

// Récupérer les entrées existantesList<String> messages = new ArrayList<String>();List<String> timestamps = new ArrayList<String>();try {

ResultSet rs = db.execute("select * from demo order by Timestamp");for (int i = 0; rs.isValidRow(); ++i, rs.next()) {

messages.add(rs.getFieldAsString(0));timestamps.add(rs.getFieldAsString(1));

}rs.close();

} catch (DatabaseException e) {Window.alert(e.toString());

}

Notez que l’API ressemble à ce qu’on ferait avec JDBC en Java natif.

De même, pour insérer une valeur, on procèdera comme suit :

// Ajouter une entrée dans la basetry {

db.execute("insert into demo values (?, ?)", new String[] { msg,Long.toString(System.currentTimeMillis()) });

updateMessages();msgBox.setText("");

} catch (DatabaseException e) {Window.alert(e.toString());

}

Le code complet de l’exemple est accessible en annexe 6.

Enfin, la page HTML correspondante :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>

<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>GWT+Gears</title><script type="text/javascript" language="javascript"

src="gwtchap1124/gwtchap1124.nocache.js"></script>

</head>

<body><h1>Demo GWT+Gears</h1><div id="gears">

</body></html>

La figure 11.12 illustre le résultat dans un navigateur en mode web. Vous pouvezvérifier que chaque fois que vous revenez sur la page, vous retrouvez la liste des messagesque vous avez entrés précédemment, grâce à la base de données locale.

Page 170: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

156 Chapitre 11. Bibliothèques tierces

Figure 11.12 — Visuel de l’API Gears

Note importante

Il n’est actuellement possible de déboguer une application GWT utilisant Gearsque sous Windows ; sur les autres plates­formes comme Mac OS X ou Linux, lemode hosted ne fonctionnera pas et une erreur sera générée lors du lancement del’application. Néanmoins, malgré cette erreur, il est toujours possible d’utiliser le boutonCompile/Browse pour lancer l’application en mode web.

Cette restriction sera levée avec l’apparition de GWT 2.0 ; en effet cette dernière versionintègrera un mode d’exécution dit « Out of Process Hosted Mode », qui découplera lenavigateur du noyau du hosted mode, et permettra ainsi une plus grande indépendanceenvers la plate­forme (lire à ce sujet le chapitre 12 sur GWT 2.0).

Le plugin Gears

Mis à part avec le navigateur Chrome (provenant de Google) pour lequel la fonc-tionnalité Gears est intégrée d’origine, l’utilisation de Gears sur les autres navigateursnécessite l’installation d’un plugin. Gears gère normalement le téléchargement duplugin lors de la première utilisation. Cependant, il existe toujours la possibilité que leplugin ne puisse pas être installé, ou que l’application soit accédée depuis un navigateurnon compatible.

Il existe heureusement une technique pour remplacer la page « normale » faisantappel à Gears par une page alternative, qui pourra selon le cas soit afficher un messaged’erreur, soit permettre un fonctionnement en mode dégradé sans Gears.

Pour cela deux étapes sont nécessaires :

1. créer le point d’entrée alternatif ;

2. le déclarer dans le fichier module.

Page 171: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

11.2 Bibliothèques utilitaires 157

Le point d’entrée alternatif peut être n’importe quel point d’entrée GWT, parexemple :

package oge.gwt.chap1124.client;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.ui.HTML;import com.google.gwt.user.client.ui.RootPanel;

/*** Ce point d’entrée sera invoqué si Gears n’est pas* disponible sur la plateforme.*/public class GwtGearsDemoNoGears implements EntryPoint {

public void onModuleLoad() {RootPanel rootPanel = RootPanel.get("gears");rootPanel.add(new HTML(

"<p><font color=\"red\">Google Gears n’estpas disponible sur ce navigateur.<br> " +"<p>Veuillez l’installer à partir de<a href=’http://tools.google.com/gears’>" +"cette page</a> et recharger l’application.</font>"));

}}

Le code « magique » qui effectue l’aiguillage vers ce point d’entrée dans le fichiermodule est le suivant :

<!-- Remplacer le point d’entrée standard par un point d’entrée alternatifsi Gears n’est pas installé --><replace-with class="oge.gwt.chap1124.client.GwtGearsDemoNoGears">

<when-type-is class="oge.gwt.chap1124.client.GwtGearsDemo"/><when-property-is name="gears.installed" value="false"/>

</replace-with>

Lorsqu’on essaye d’accéder à cette page alors que Gears n’est pas installé, on peutvoir le résultat présenté en figure 11.13.

Figure 11.13 — Gears, page non disponible

L’utilisateur pourra alors installer le plugin correspondant à sa configuration avantde continuer.

Page 172: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 173: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

GWT 2.0

12

ObjectifCe chapitre vous permettra de vous familiariser avec les principales nouveautésintroduites par GWT 2.0 que sont :

- la possibilité de déboguer dans tout navigateur avec OOPHM (Out Of ProcessHosted Mode) ;

- la possibilité de diviser du code généré en différents blocs avec le code splitting ;

- la construction d’interfaces via un langage descriptif avec UiBinder ;

- la gestion des ressources avec ClientBundle.

Depuis ses débuts, GWT est en évolution continue, et quasiment chaque versiona apporté des améliorations significatives (voir l’historique des versions au § 1.3.3).La dernière évolution porte le nom de 2.0 ; l’incrémentation du numéro de versionmajeure traduit l’intégration de fonctionnalités de premier plan.

Sans parler de révolution, car les principes de base sont toujours les mêmes, cetteversion s’attache notamment à progresser davantage sur les aspects d’efficacité etd’optimisation des applications GWT. Heureusement, la compatibilité ascendanteest aussi un souci des concepteurs de GWT, et la quasi-totalité de ce qui a été écritprécédemment dans cet ouvrage s’applique aussi bien aux versions 1.6/1.7 qu’à laversion 2.0.

Page 174: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

160 Chapitre 12. GWT 2.0

Il n’est pas question ici de lister exhaustivement les différences avec la versionprécédente, mais on va cependant détailler les nouveautés les plus significatives :

• Out Of Process Hosted Mode, la nouvelle architecture du hosted mode, qui permetenfin de déboguer dans n’importe quel navigateur ;

• la notion de code splitting, qui optimise le chargement des applications volumi-neuses en donnant des indications au compilateur pour découper le code sourceen plusieurs parties ;

• l’introduction d’un langage déclaratif de description des interfaces et sonprocesseur, UiBinder ;

• l’amélioration du traitement des ressources avec ClientBundle.

12.1 OBTENIR LA DERNIÈRE VERSION DE GWT

Pour profiter des nouvelles fonctionnalités de GWT 2.0, il vous faudra obtenir uneversion de développement récente de GWT. Vous avez le choix entre plusieursoptions :

• soit utiliser un milestone que Google met à disposition surhttp://code.google.com/p/google-web-toolkit/downloads (sélectionnezDeprecated downloads pour voir les versions intermédiaires, milestones et releasecandidates) ;

• soit utiliser un des snapshots que la société SFEIR met périodiquement àdisposition de tous sur http://code.google.com/p/sfeir/downloads/list ;

• soit encore, pour avoir la version la plus récente, récupérer les sources de GWTdepuis le repository Subversion public du projet et le compiler soi-même. Si vousn’avez pas peur de « mettre les mains dans le cambouis », la dernière optionn’est pas excessivement complexe ; nous allons la détailler ci-après.

12.1.1 Prérequis

Les prérequis sont :

• un client SVN (Subversion), téléchargeable depuishttp://subversion.tigris.org/getting.html ;

• une version d’ant supérieure à 1.7.1, qu’on peut télécharger depuishttp://ant.apache.org/bindownload.cgi.

On suppose que les commandes svn et ant sont installées et que votre PATH estconfiguré correctement pour y accéder.

Note

Mac OS X inclut un client SVN en standard, mais celui­ci est trop ancien et nefonctionnera pas avec GWT. Vous devrez donc tout de même installer un client SVNrécent.

Page 175: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.2 OOPHM 161

La compilation de GWT nécessite des outils spécifiques (notamment pour générerle hosted mode). La compilation de ces outils eux-mêmes est possible également, maiscomplexe ; heureusement le repository contient une version précompilée de ces outils.

12.1.2 Génération de GWT

1. À l’endroit où vous le souhaitez, créez un dossier dédié pour cette opération.On supposera que ce ce dossier s’appelle « gwt ».

2. Ouvrez un terminal (invite de commande pour Windows) et allez dans cenouveau dossier.

3. Tapez la commande suivante pour récupérer les outils précompilés :svn checkout http://google-web-toolkit.googlecode.com/svn/tools/

tools

4. Tapez la commande suivante pour récupérer les sources de GWT :svn checkout http://google-web-toolkit.googlecode.com/svn/trunk/

trunk

5. Allez dans le dossier trunk qui vient d’être créé :cd trunk

6. Lancez la construction :

– pour genérer toutes les plates-formes (Windows, Mac, Linux) :ant

– pour genérer la plate-forme courante seulement :ant dist-dev

Si tout se passe correctement, les JAR générés se trouvent sous build/lib, lesarchives complètes sous build/dist avec une version correspondant à 0.0.0 (gwt-windows-0.0.0.zip, gwt-mac-0.0.0.tar.gz, gwt-linux-0.0.0.tar.bz2).

12.2 OOPHM

Le hosted mode est une pièce essentielle de GWT ; en effet il permet au développeurd’utiliser un débogueur Java standard pour déboguer du code qui, au final, tournera sousforme de JavaScript dans un navigateur. Par conséquent, le hosted mode doit émuler unnavigateur pour permettre au code Java d’interagir avec ce dernier, de la même façonque le code JavaScript interagira avec le navigateur dans lequel il tournera.

Dans les versions 1.x de GWT, on arrive à cette fin en embarquant une versionmodifiée d’un navigateur dans le hosted mode ; le navigateur embarqué cohabite doncavec le hosted mode dans le même processus système.

Page 176: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

162 Chapitre 12. GWT 2.0

Si cette approche s’est avérée exploitable, elle présente cependant un certainnombre d’inconvénients :

• l’intégration d’un navigateur avec le hosted mode nécessite beaucoup demodifications. Conséquence de ceci, seul un navigateur est supporté pourchaque plate-forme (Windows, Mac, Linux) ;

• pour la même raison, l’intégration d’une nouvelle version d’un navigateur estproblématique ;

• la technique d’intégration utilisée empêche de nombreux plugins de fonctionner(en particulier Google Gears comme vu au § 11.2.3) ;

• de nombreux autres effets de bord indésirables existent.

C’est pour remédier à tous ces problèmes que Google a introduit la notion de OutOf Process Hosted Mode (mode hôte hors processus). Dans cette nouvelle architecture,le hosted mode n’embarque pas un navigateur, mais dialogue avec un navigateurstandard au travers d’un mécanisme de type plugin. Les avantages sont évidents :

• pour peu que la compatibilité des plugins soit assurée, le support d’une nouvelleversion de navigateur ne devrait nécessiter aucun travail supplémentaire ;

• le hosted mode pourra fonctionner avec n’importe quel navigateur (supporté) surn’importe quelle plate-forme ;

• les outils de debogage et plugins fonctionneront puisque le navigateur ne serapas modifié ;

• les différentes variantes de GWT (gwt-dev-mac.jar, gwt-dev-windows.jar, gwt-dev-linux.jar) pourront éventuellement fusionner, puisque la majorité desdifférences provient des implémentations particulières du hosted mode.

Le noyau du nouveau hosted mode communique avec le plugin au moyen d’unprotocole réseau TCP (figure 12.1), ce qui offre un bénéfice supplémentaire puisqu’ilsera ainsi possible de déboguer une session Internet Explorer tournant sur une machineWindows depuis un environnement de développement et un hosted mode hébergés surune machine Linux !

Les plugins existants aujourd’hui sont les suivants :

• Firefox 2, 3 et 3.5 : les plugins correspondants (respectivementgwt-dmp-ff2.xpi, gwt-dmp-ff3.xpi et gwt-dmp-ff35.xpi) se trouvent à l’URLhttp://google-web-toolkit.googlecode.com/svn/trunk/plugins/xpcom/prebuilt/Pour l’installer il suffit de cliquer sur le fichier XPI correspondant depuis Firefox,et confirmer l’installation du plugin.

• Internet Explorer 6, 7 et 8 : l’extension se trouve à l’URL http://google-web-toolkit.googlecode.com/svn/trunk/plugins/ie/prebuiltPour l’installation, téléchargez le fichier oophm.dll dans un dossier temporairelocal, puis dans une invite de commande, saisissez regsrv32 oophm.dll etredémarrez IE.

Page 177: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.2 OOPHM 163

• Safari 3 et 4 (Mac seulement) : le plugin se trouve à l’URL http://google-web-toolkit.googlecode.com/svn/trunk/plugins/webkit/prebuiltTéléchargez le fichier oophm.dmg (image disque), montez-le dans le Finder(double-clic) et exécutez l’installeur.

• Chrome : il faut utiliser la version « DevChannel » de Chromium (la ver-sion Open Source de Chrome), car la version stable courante ne supportepas encore les extensions. L’extension se trouve à l’URL http://google-web-toolkit.googlecode.com/svn/trunk/plugins/npapi/prebuiltPour l’installer, cliquez sur le fichier gwtdmp.crx depuis Chrome.

Figure 12.1 — Communication entre le hosted mode et le navigateur avec OOPHM

Terminologie

GWT 2.0 introduira un léger changement dans la terminologie officielle, destiné àclarifier les choses. Ainsi, Hosted Mode deviendra Development Mode et Web Mode

deviendra Production Mode. OOPHM quant à lui sera appelé In­Browser Development

Mode.

Page 178: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

164 Chapitre 12. GWT 2.0

12.2.1 Utilisation

Côté développement, il vous faudra activer l’OOPHM qui ne l’est pas par défaut. Enrègle générale, il suffit d’ajouter le fichier JAR gwt-dev-oophm.jar en tête du classpathJava. Cependant, si vous utilisez le plugin Google pour Eclipse, il vous suffira de cocherune case dans la configuration d’exécution.

Dans le détail :

1. Décompressez l’archive générée par la compilation ou téléchargée, commen’importe quelle version de GWT (voir § 2.2.2).

2. Si votre archive décompressée ne comporte qu’un fichier gwt-dev.jar au lieud’un fichier gwt-dev-mac.jar, gwt-dev-windows.jar ou gwt-dev-linux.jar

(ce qui sera le cas dans la version finale de GWT 2.0), il vous faudra alorsle renommer correctement selon votre plate-forme pour que cette version deGWT soit reconnue par le plugin Google. Bien sûr, le plugin sera mis à jour lorsde la sortie de GWT 2.0.

3. Ajoutez la nouvelle version de GWT à la configuration d’Eclipe :

– dans Eclipse, ouvrez Preferences > Google > Web Toolkit (figure 12.2),– cliquez sur le bouton Add et choisissez le répertoire qu’on vient de créer

(figure 12.3),– cliquez sur OK,– cochez la version que vous venez d’ajouter (figure 12.4), puis cliquez sur OK

pour fermer les préférences.

Figure 12.2 — Préférences Eclipse : liste des versions de GWT

Figure 12.3 — Préférences Eclipse : Ajout d’une nouvelle version de GWT

Page 179: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.2 OOPHM 165

Figure 12.4 — Préférences Eclipse : liste des versions de GWT avec la nouvelle version commedéfaut

4. Assurez-vous que la configuration d’exécution de votre projet est bien régléepour OOPHM :

– dans Eclipse, ouvrez le menu Run > Run configuration,

– sélectionnez votre projet dans la partie gauche,

– dans l’onglet GWT, cochez la case Launch URL using OOPHM,

– cliquez sur Apply puis Close pour valider vos modifications.

5. Pour lancer l’application, faites exactement comme d’habitude : clic droit surle projet, puis Run As... (ou Debug As...) > Web Application.

6. Surveillez la console. Après quelques secondes, un message similaire au suivantapparaît :Using a browser with the GWT Development Plugin, please browse to

the following URL:

http://localhost:64130/Sandbox.html?gwt.hosted=10.0.2.1:9997

7. Lorsque ce message s’affiche, ouvrez un navigateur équipé du plugin OOPHM,copiez l’URL mentionnée et collez-la dans la barre d’adresse du navigateur.

8. Le plugin établit la communication avec le processus du hosted mode qui tournedans Eclipse; vous pouvez désormais mettre des points d’arrêt et vérifier quetout fonctionne.

Note

Les appels entre le plugin OOPHM et le code Java sont synchrones ; par conséquent,si vous avez mis un point d’arrêt dans une méthode Java, le navigateur apparaîtrabloqué tant que la méthode ne retournera pas.

Page 180: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

166 Chapitre 12. GWT 2.0

12.3 CODE SPLITTING & SOYC

Avec la complexité grandissante des applications AJAX, le volume de code JavaScriptà télécharger initialement tend à augmenter, et les applications GWT n’échappentpas à la règle. Par défaut, la compilation GWT génère du JavaScript dit « obfuscated »c’est-à-dire compacté au maximum, mais ce n’est pas suffisant.

Pour aller plus loin, GWT 2.0 introduit la notion de « code splitting » (séparationde code). Grâce à ce concept, le programmeur peut indiquer au compilateur GWTdes endroits de son programme où une partie additionnelle de code peut être chargée.Ces endroits sont appelés « split points » (points de séparation).

Avec cette information, le compilateur peut découper le code JavaScript enplusieurs parties, qui seront chargées « à la demande » lorsque le programme atteindraun split point.

12.3.1 Insérer un split point

Pour insérer un split point dans votre code, il suffit d’appeler la méthode statiqueGWT.runAsync(). Cette méthode prend en paramètre un objet de type RunAsyncCall-

back, qui contient le code dont on souhaite différer le chargement.

De façon similaire aux callbacks associés aux appels RPC (AsyncCallback, voirchapitre 5 : Communiquer avec le serveur), le RunAsyncCallback doit implémenterdeux méthodes :

• void onSuccess() sera appelé lorsque le code additionnel aura été chargé ;• void onFailure(Throwable reason) sera appelé si le code additionnel n’a pas pu

être chargé pour une raison quelconque (réseau ou serveur devenu indisponiblepar exemple).

RunAsyncCallback se présente donc comme un event handler, à ceci près quel’événement auquel il réagit est le chargement du code nécessaire à la poursuite del’exécution. Le code dont le chargement doit être différé est donc le contenu de laméthode onSuccess(), ainsi que tout ce dont il dépend.

À titre d’exemple, prenons le code d’exemple standard généré pour un nouveauprojet GWT. Ce code contient une méthode sendNameToServer() qui récupère lecontenu d’un champ texte, effectue un appel RPC et affiche la réponse du serveur :

private void sendNameToServer() {sendButton.setEnabled(false);String textToServer = nameField.getText();textToServerLabel.setText(textToServer);serverResponseLabel.setText("");greetingService.greetServer(textToServer, new AsyncCallback<String>() {

public void onFailure(Throwable caught) {Window.alert("Rpc failure");sendButton.setEnabled(true);

}

Page 181: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.3 Code splitting et SOYC 167

public void onSuccess(final String result) {serverResponseLabel.setHTML(result);dialogBox.center();closeButton.setFocus(true);

}});

}

Or cette méthode n’a pas besoin d’être chargée initialement, puisqu’elle n’estappelée que lors du clic sur un bouton ou un appui sur Enter. Si on souhaite différerson chargement jusqu’à son appel effectif, on pourra transformer le code comme suit :

private void sendNameToServer() {GWT.runAsync(new RunAsyncCallback() {

public void onFailure(Throwable reason) {GWT.log("runAsync failed", reason);

}public void onSuccess() {

doSendNameToServer();}

});}private void doSendNameToServer() {

sendButton.setEnabled(false);String textToServer = nameField.getText();textToServerLabel.setText(textToServer);serverResponseLabel.setText("");greetingService.greetServer(textToServer, new AsyncCallback<String>() {

public void onFailure(Throwable caught) {Window.alert("Rpc failure");sendButton.setEnabled(true);

}public void onSuccess(final String result) {

serverResponseLabel.setHTML(result);dialogBox.center();closeButton.setFocus(true);

}});

}

Ce qu’on a fait ici tout simplement, c’est qu’on a déplacé le corps de la méthodesendNameToServer() dans une nouvelle méthode doSendNameToServer(), et laméthode sendNameToServer() contient désormais un appel à GWT.runAsync() quiinvoquera doSendNameToServer() lorsque le code correspondant aura été chargé.

Cette simple déclaration a pour effet d’indiquer au compilateur GWT qu’il doit, sipossible, placer le code JavaScript correspondant à la méthode doSendNameToServer()

dans un fichier séparé ; ce dernier ne sera chargé que lorsqu’on en aura besoin, c’est-à-dire dans notre exemple lors de l’appel à la méthode sendNameToServer().

Si on compile et qu’on exécute l’application modifiée, on peut constater deuxchoses :

• d’une part, le comportement de l’application d’un point de vue externe estinchangé (c’est le but) ;

• d’autre part, le volume du chargement initial a été réduit d’environ un tiers.

Page 182: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

168 Chapitre 12. GWT 2.0

Sur une application comme celle-ci, le gain est marginal, mais sur une applicationmoins triviale, la différence de temps de chargement initial peut être très sensible !Ainsi, en insérant des split points à des endroits judicieux, il est assez simple de réduirede moitié la taille du téléchargement initial pour une application GWT typique.

Attention toutefois, car le résultat n’est pas toujours comme on l’attend. Il estpossible que le compilateur décide d’inclure dans le téléchargement initial du codequ’on pensait différé, la plupart du temps à cause d’une dépendance indirecte passéeinaperçue. Pour comprendre comment le compilateur GWT procède au découpage,et corriger le code pour que la séparation se fasse comme on le souhaite, GWT 2.0introduit la notion de « Story of your compile » (l’histoire de votre compilation).

12.3.2 Story Of Your Compile (SOYC)

SOYC peut être vu comme une sorte de compte-rendu détaillé de la compilation. Cecompte-rendu intègre, entre autres, les différents morceaux qui résultent du découpageen fonction des split points rencontrés dans le code.

La génération d’un rapport SOYC se fait en deux phases :

1. des options spécifiques sont passées au compilateur GWT pour lui indiquer degénérer les informations de découpage « brutes » ;

2. le rapport lui même est généré à partir de ces informations par l’applicationSoycDashboard, inclue dans la distribution GWT.

Le processus est à ce jour très peu documenté et assez délicat à faire fonctionner;voyons en détail comment le mettre en œuvre avec Eclipse et le plugin Google.

Compiler pour SOYC

1. Dans la fenêtre de compilation GWT (obtenue lorsqu’on clique sur l’icône

Icône compilation GWT dans la barre d’outils Eclipse), cliquez sur Advancedpour afficher les options avancées, et ajoutez les options -soyc -extra extra

aux options de compilation, comme sur la figure 12.5.

2. Cliquez sur Compile pour lancer la compilation. À l’issue de la compilation, sitout s’est bien passé, le compilateur aura créé un dossier extra contenant lesinformations de compilation brutes.

Explication des options

-extra demande au compilateur de générer des informations sur la compilation dansun sous­dossier nommé extra.-soyc lui demande en plus d’y ajouter les informations nécessaires à la générationultérieure du rapport SOYC.Note : ces options sont retenues d’une invocation à l’autre de la compilation ; si vousne désirez plus générer de rapport SOYC, il faudra effacer les options avancées de lafenêtre de compilation.

Page 183: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.3 Code splitting et SOYC 169

Figure 12.5 — Plugin GWT : options de compilation pour SOYC

Générer le rapport SOYC

Pour générer le rapport, on va utiliser une run configuration d’Eclipse, mais toutes lesoptions qui permettent de lancer une classe Java sont également valides (target ant,etc.) :

1. Le programme doit avoir accès au fichier gwt-soyc-vis.jar contenu dansla distribution GWT. Le plus simple pour ne pas s’embarasser de cheminsabsolus est de créer un sous-dossier lib dans le projet et d’y copier le fichiergwt-soyc-vis.jar depuis le dossier gwt-xxx-0.0.0.

2. Ouvrez l’écran de configuration des run configurations (menu Run > Runconfigurations..., figure 12.6).

3. Créez une nouvelle configuration de type Java application :

– faites un clic droit sur Java application puis New,

– nommez la nouvelle configuration « SoycDashboard »,

– assurez-vous qu’elle correspond bien au projet souhaité, au besoin choisissez-le en cliquant sur Browse...,

– dans le champ Main class (figure 12.7), saisissez« com.google.gwt.soyc.SoycDashboard » (ou bien cliquez sur Search... etsélectionnez la classe en tapant une partie de son nom).

Page 184: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

170 Chapitre 12. GWT 2.0

Figure 12.6 — Liste des configurations de lancement Eclipse

Figure 12.7 — Onglet principal de la configuration de lancement Eclipse pour la génération durapport SOYC

Page 185: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.3 Code splitting et SOYC 171

4. Cliquez sur l’onglet Arguments (figure 12.8) :

– dans le champ Program arguments, saisissez -resources

lib/gwt-soyc-vis.jar -soycDir extra/sandbox/soycReport/

-symbolMapsDir extra/sandbox/symbolMaps/ -out soyc,

– dans le champ VM arguments, saisissez -Xmx1024M,

– dans Working Directory, assurez-vous que Default est coché.

Figure 12.8 — Onglet « Arguments » de la configuration de lancement Eclipse pour lagénération du rapport SOYC

5. Cliquez sur Apply pour sauvegarder la configuration, puis Run pour démarrer.La console montre l’évolution de la génération :Generating the Story of Your Compile...

Finished creating reports for permutation.

Finished creating reports for permutation.

Finished creating reports for permutation.

Finished creating reports for permutation.

Finished creating reports for permutation.

Finished creating reports for permutation.

Finished creating reports. To see the dashboard, open index.html in

your browser.

6. Une fois la génération terminée, comme indiqué ouvrez le fichiersoyc/index.html avec un navigateur.

Page 186: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

172 Chapitre 12. GWT 2.0

Explication des options

-resources désigne le fichier gwt-soyc-vis.jar, copié précédemment dans le sous­dossier lib.-soycDir et -symbolMapsDir désignent les dossiers contenant les données généréesprécédemment par le compilateur. Il convient de remplacer « sandbox » dans l’exempleen figure 12.7 par le nom du module GWT de votre projet.

-out indique au programme de générer les fichiers résultats dans un sous­dossiernommé soyc.

Note

Pour relancer la génération du rapport ultérieurement, il suffira d’invoquer de nouveaula run configuration qu’on vient de créer (après avoir effectué une compilation bien sûr).

Si ça ne fonctionne pas...

Les paramètres à saisir sont fortement sujets à erreur, et le message produit n’est pastoujours en rapport avec le problème... voici quelques erreurs qui peuvent survenir :

• Error creating html file. error in opening zip file

Cette erreur se produit si le fichier gwt-soyc-vis.jar désigné par l’option -

resources n’est pas accessible.• Cannot open file extra/sandbox/soycRepor/stories0.xml (No such file

or directory)

Le dossier désigné par l’option -soycDir est probablement erroné. Vérifiez qu’ila bien été généré lors de la compilation; ce dossier doit contenir un ensemblede fichiers du type splitPoints0.xml.gz, stories0.xml.gz, dependencies0.xml.N’oubliez pas que le chemin spécifié est relatif à la racine du projet Eclipse.

• Exception in thread "main" java.lang.

NullPointerException

at com.google.gwt.soyc.Settings.readPermutationInfo

(Settings.java:221)

at com.google.gwt.soyc.SoycDashboard.main

(SoycDashboard.java:73)

Cette erreur peu glorieuse se produit lorsque le dossier désigné par l’option-symbolMapsDir est erroné...

Cette liste n’est bien sûr pas limitative.

12.3.3 Optimiser avec le code splitting

Le rapport fourni par SOYC vous sera utile pour connaître la taille des différents blocsde téléchargement, en particulier celle du bloc initial.

Page 187: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.3 Code splitting et SOYC 173

Parfois, il arrive qu’on pense avoir sorti une partie du bloc initial, mais qu’elley figure toujours. Pour cela, le rapport SOYC vous permettra de suivre la chaîne dedépendances pour comprendre d’où vient la dépendance restante.

Un pattern utile en collaboration avec le code splitting est Async provider ; il permetd’isoler un groupe de fonctionnalités dans un bloc tout en fournissant un point d’entréeunique qui évite les références directes pouvant causer une inclusion non souhaitéedu code dans un autre bloc.

Imaginons une classe Provider qui fournit un certain nombre de méthodes, etqu’on souhaite placer dans un bloc de code séparé qui est chargé au besoin. Pourcela, on oblige les utilisateurs de cette classe à passer par une méthode publique quiappellera un callback lorsque l’instance sera disponible.

L’interface que le client doit implémenter :

public interface AsyncClient<T> {void onUnavailable();void onAvailable(T instance);

}

Extrait du code de la classe Provider :

public class Provider {private static Provider instance = null;private Provider() {

//...}public static void getAsync(final AsyncClient<Provider> client) {

GWT.runAsync(new RunAsyncCallback() {public void onFailure(Throwable reason) {

client.onUnavailable();}public void onSuccess() {

if (instance == null) {instance = new Provider();

}client.onAvailable(instance);

}});

}}

Utilisation de la classe :

Provider.getAsync(new AsyncClient<Provider>() {public void onAvailable(Provider instance) {

// l’instance de Provider est disponible}public void onUnavailable() {

// un problème est survenu...}

});

D’autres patterns vont certainement apparaître en conjonction avec le code splitting.

Page 188: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

174 Chapitre 12. GWT 2.0

12.4 UIBINDER

Un des aspects manquants dans GWT était la possibilité de construire des interfacesstatiquement au travers d’un langage déclaratif, comme le permettent de nombreuxtoolkits graphiques. L’intérêt d’un langage de construction déclaratif est qu’il permet deséparer clairement ce qui est purement statique (les composants UI qui ne changentpas) du comportement dynamique (le comportement de l’interface en réaction auxactions de l’utilisateur).

GWT 2.0 comble ce manque en introduisant UiBinder. Concrètement, il existeune interface générique UiBinder qui se présente comme suit :

public interface UiBinder<U, O> {/***Creates and returns the root object of the UI, and fills*any fields of owner tagged with {@link UiField}.**@param owner the object whose {@literal @}UiField needs will be filled*/U createAndBindUi(O owner);

}

Cette interface est paramétrée pas les types suivants :

• U est le type de l’élément construit par le binder ;• O est le type d’un objet qui peut contenir des champs liés, c’est-à-dire des

références à des éléments construits par UiBinder.

La seule méthode de cette interface, createAndBindUi(), a un double rôle :

• construire l’instance de U à partir du fichier de description XML ;• renseigner certaines variables de l’objet O passé en paramètre avec la référence

de l’élément de l’interface correspondant. Les variables à renseigner sont taggéespar l’annotation @UiField. Ceci permet à l’objet O d’accéder à ce dont il a besoinpour mettre en place le comportement souhaité.

12.4.1 Utilisation

Pour construire une interface avec UiBinder, les étapes sont les suivantes :

1. Importez le module UiBinder dans le projet ; pour cela il faut ajouter la lignesuivante dans le fichier module :

<inherits name="com.google.gwt.uibinder.UiBinder"/>

Page 189: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.4 UiBinder 175

2. Définissez l’interface désirée au format XML dans un fichier .ui.xml. Il n’existepas à cette heure de spécification complète du format, mais celui-ci est assezsimple pour être compris à partir d’un exemple :

<gwt:UiBinder xmlns:ui=’urn:ui:com.google.gwt.uibinder’xmlns:gwt=’urn:import:com.google.gwt.user.client.ui’>

<div><gwt:HorizontalPanel>

<gwt:Label text="Votre nom :" /><gwt:TextBox ui:field="nomBox" /><gwt:Button ui:field="submitButton" text="OK" />

</gwt:HorizontalPanel></div>

</gwt:UiBinder>

3. Choisissez un type Java (O) qui recevra les références, et marquez avec l’anno-tation UiField les variables à renseigner :

@UiFieldTextBox nomBox;

4. Si nécessaire, dans le type O, désignez des méthodes en tant que handlers surcertains widgets avec l’annotation UiHandler :

@UiHandler("submitButton")void buttonClicked(ClickEvent event) {

// faire quelque chose...}

5. Dans le code Java, déclarez une interface qui étend UiBinder en spécifiant lestypes désirés pour U et O, par exemple :

@UiTemplate("MyClient.ui.xml")interface MyUiBinder extends UiBinder<Panel, MyClient> {}

6. Obtenez une instance de ce type grâce à l’omniprésent GWT.create() :

private static final MyUiBinder binder = GWT.create(MyUiBinder.class);

7. Appelez createAndBindUi() en lui passant une instance de O :

MyClient client = new MyClient();Panel panel = binder.createAndBindUi(client);

L’appel retourne un objet U (ici une instance de Panel) et remplit les champstaggés dans l’objet O passé en paramètre (ici client).

Page 190: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

176 Chapitre 12. GWT 2.0

Notes

Étape 2 :La présence d’un élément XML du namespace « gwt » se traduit par l’instanciationd’un widget du type spécifié. Ce widget sera ajouté comme fils au widget instanciépar l’élément XML parent :– les attributs (sans namespace) de ces éléments spécifient des valeurs pour lespropriétés du widget ;– l’attribut spécial ui:field désigne une variable du type O qui recevra la référencevers le widget lors du binding.Notez pas ailleurs qu’on peut inclure des éléments HTML littéraux (texte, <DIV>, etc.).Étape 4 :Le nom de la méthode n’est pas important, c’est le type du paramètre qui va déterminerde quel type de handler il s’agit. Ici, le paramètre est de type ClickEvent : la méthodesera enregistrée avec addClickHandler().Étape 5 :L’annotation UiTemplate permet de désigner le fichier de déclaration à utiliser. Cetteannotation est optionnelle : par défaut, GWT cherchera un fichier situé dans le mêmepackage que le type O (ici MyClient), portant le même nom que celui­ci avec un suffixede .ui.xml, donc dans notre cas MyClient.ui.xml.

12.4.2 Un exemple

Nous allons illustrer l’utilisation d’UiBinder par un exemple simple et concret.

Souvenez-vous du widget SexeRadio qu’on avait utilisé comme exemple pour illus-trer la fabrication d’un widget « maison » au § 10.2 Utiliser la classe Composite. Nousallons recréer ce widget, mais cette fois-ci, au lieu d’instancier programmatiquementles sous-widgets, nous allons déléguer cette opération à UiBinder.

Tout d’abord, traduisons la hiérarchie de widgets dans le format spécifique XMLUiBinder. On obtient ceci :

<gwt:UiBinder xmlns:ui=’urn:ui:com.google.gwt.uibinder’xmlns:gwt=’urn:import:com.google.gwt.user.client.ui’>

<gwt:HorizontalPanel><gwt:Label text="Sexe :" /><gwt:VerticalPanel>

<gwt:RadioButton name=’sexeradio’ text=’M’ui:field=’maleRadio’ />

<gwt:RadioButton name=’sexeradio’ text=’F’ui:field=’femaleRadio’ />

</gwt:VerticalPanel></gwt:HorizontalPanel>

</gwt:UiBinder>

La base du nouveau widget reste un Composite. Ce widget jouera le rôle du type O

pour UiBinder car on souhaite en récupérer les références vers les deux RadioButtons(d’où la présence des attributs ui:field dans le fichier XML) :

Page 191: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

12.4 UiBinder 177

public class SexeRadio2 extends Composite {@UiFieldRadioButton maleRadio;@UiFieldRadioButton femaleRadio;// ...

}

Les noms des variables doivent correspondre aux valeurs des attributs ui :field dufichier XML. Ensuite, dans cette même classe, nous allons déclarer l’interface UiBinder

et obtenir une instance grâce à GWT.create() :

@UiTemplate("SexeRadio2.ui.xml")interface MyUiBinder extends UiBinder<Panel, SexeRadio2> {}private static final MyUiBinder binder = GWT.create(MyUiBinder.class);

Finalement, nous allons instancier l’interface dans le constructeur de notrenouveau widget. Comme il s’agit d’un composite, le panel sera passé à initWidget()

pour en faire le widget de base du composite :

public SexeRadio2() {final Panel panel = binder.createAndBindUi(this);initWidget(panel);

}

On note également que c’est this qui est passé en paramètre au binder, puisquec’est bien dans l’objet courant qu’on souhaite récupérer les références vers lesRadioButtons. On peut alors inclure les méthodes qui permettent de savoir quelbouton est sélectionné :

public boolean isM() {return maleRadio.getValue();

}public boolean isF() {

return femaleRadio.getValue();}

Pour le plaisir (et pour vérifier que cela fonctionne bien sûr), nous allons associerdes handlers aux RadioBoutons qui affichent simplement une trace dans la fenêtre duhosted mode :

@UiHandler("maleRadio")void maleClicked(ClickEvent event) {

GWT.log("C’est un garçon !", null);}@UiHandler("femaleRadio")void femaleClicked(ClickEvent event) {

GWT.log("C’est une fille !", null);}

Le widget ainsi créé s’utilise exactement comme le précédent ; la seule différence,mais de taille, c’est que la construction de l’interface s’est faite de façon totalementdéclarative dans le fichier XML, alors que la classe Java se cantonne à gérer lapartie dynamique (comportement). Le récapitulatif de la classe SexeRadio2 estaccessible en annexe 7.

Page 192: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

178 Chapitre 12. GWT 2.0

12.5 CLIENTBUNDLE

ClientBundle permet de grouper des ressources quelconques (y compris images, feuillesCSS et ressources binaires). L’avantage évident est de limiter le nombre de télécharge-ments, ce qui réduit l’overhead causé par un grand nombre de téléchargements.

Les possibilités ouvertes par ClientBundle sont nombreuses ; illustrons-les avec unexemple.

Tout d’abord, il faut importer le module Resources dans le fichier module :

<inherits name="com.google.gwt.resources.Resources" />

Ensuite, on définit une interface qui hérite de ClientBundle ; chaque méthodepermettra d’accéder à une ressource dont la source est spécifiée par une annotation,par exemple :

public interface MyResources extends ClientBundle {public static final MyResources INSTANCE =

GWT.create(MyResources.class);

@Source("style.css")CssResource style();

@Source("data.xml")TextResource xmlData();

@Source("document.pdf")DataResource document();

@Source("logo.png")ImageResource logo();

}

Les ressources doivent être disponibles au moment de la compilation ; le compila-teur se charge d’effectuer le groupage de façon totalement automatique et transparente.

Côté client, on obtient une référence vers un objet qui implémente l’interfacequ’on a défini en appelant GWT.create(MyResources.class) ; c’est ensuite à l’appli-cation d’utiliser une des méthodes ci-dessous pour accéder au contenu des différentesressources, en fonction de son type :

• TextResource fournit une méthode getText() qui retourne le contenu sousforme de String ;

• DataResource fournit une méthode getUrl() qui retourne une URL absoluedonnant accès à la ressource ;

• CssResource permet de manipuler une ressource CSS ;• ImageResource permet d’obtenir des informations sur l’image, et son URL.

Page 193: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes

Dans cette partie, retrouvez :

• La liste des classes de la bibliothèque d’émulation JRE (chapitre 3)• Un exemple de FlexTable avec cellule baladeuse (chapitre 4)• Un exemple d’appel à un service RPC (chapitre 5)• Un exemple de mise en œuvre du mécanisme d’historique (chapitre 8)• L’appel à un service web JSON (chapitre 9)• Un exemple d’utilisation de l’API Google Gears (chapitre 11)• Un exemple d’utilisation d’UiBinder pour créer un widget composite

(chapitre 12)

Page 194: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 195: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 181

Liste des classes de la bibliothèque d’émulation JRE (chapitre 3)

Package Classes émuléesjava.lang ArithmeticException

ArrayIndexOutOfBoundsException

ArrayStoreException

AssertionError

Boolean

Byte

CharSequence

Character

Class

ClassCastException

Cloneable

Comparable

Deprecated

Double

Enum

Error

Exception

Float

IllegalArgumentException

IllegalStateException

IndexOutOfBoundsException

Integer

Iterable

Long

Math

NegativeArraySizeException

NullPointerException

Number

NumberFormatException

Object

Override

Runnable

RuntimeException

Short

StackTraceElement

String

Page 196: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

182 Aller plus loin avec GWT

Package Classes émuléesStringBuffer

StringBuilder

StringIndexOutOfBoundsException

SuppressWarnings

System

Throwable

UnsupportedOperationException

Void

java.lang.annotation Annotation

AnnotationFormatError

AnnotationTypeMismatchException

Documented

ElementType

IncompleteAnnotationException

Inherited

Retention

RetentionPolicy

Target

java.util AbstractCollection

AbstractList

AbstractMap

AbstractQueue

AbstractSequentialList

AbstractSet

ArrayList

Arrays

Collection

Collections

Comparator

ConcurrentModificationException

Date

EmptyStackException

EnumMap

EnumSet

Page 197: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 183

Package Classes émuléesEnumeration

EventListener

EventObject

HashMap

HashSet

IdentityHashMap

Iterator

LinkedHashMap

LinkedHashSet

LinkedList

List

ListIterator

Map

Map.Entry

MissingResourceException

NoSuchElementException

PriorityQueue

Queue

RandomAccess

Set

SortedMap

SortedSet

Stack

TooManyListenersException

TreeMap

TreeSet

Vector

java.io FilterOutputStream

OutputStream

PrintStream

Serializable

java.sql Date

Time

Timestamp

Page 198: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

184 Aller plus loin avec GWT

Exemple de FlexTable avec cellule baladeuse (chapitre 4)

Code source de Gwt42Tables.java

package oge.gwt.chap42.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.event.dom.client.ClickEvent;import com.google.gwt.event.dom.client.ClickHandler;import com.google.gwt.user.client.ui.Button;import com.google.gwt.user.client.ui.FlexTable;import com.google.gwt.user.client.ui.Grid;import com.google.gwt.user.client.ui.HorizontalPanel;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.user.client.ui.VerticalPanel;

public class Gwt42Tables implements EntryPoint {

private FlexTable table;private VerticalPanel buttonPanel;private int row = 0;private int col = 0;

/*** Le point d’entrée*/

public void onModuleLoad() {

// sous-classe de Button spécialisée qui fait appel à la méthode// move avec les paramètres passés à son constructeurclass DirButton extends Button{

public DirButton(String label, final int deltax,final int deltay) {

super(label);addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {move(deltax, deltay);

}});

}}

// créer la FlexTabletable = new FlexTable();table.setBorderWidth(1);table.setCellPadding(25);

// créer le groupe de boutons qui constituera// la "cellule baladeuse"buttonPanel = new VerticalPanel();buttonPanel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);

buttonPanel.add(new DirButton("^", -1, 0));HorizontalPanel hPanel = new HorizontalPanel();hPanel.add(new DirButton("&lt;", 0, -1));hPanel.add(new DirButton("&gt;", 0, +1));buttonPanel.add(hPanel);

Page 199: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 185

buttonPanel.add(new DirButton("v", +1, 0));

//positionner initialement le groupe de boutonstable.setWidget(row, col, buttonPanel);

// ajouter la tableRootPanel.get("contenu").add(table);

}

/*** Déplace le groupe de boutons* @param deltax décalage horizontal* @param deltay décalage vertical*/protected void move(int deltax, int deltay) {

// retirer le groupe de boutons de la tabletable.remove(buttonPanel);

// calculer les nouvelles positionsrow += deltax;if (row < 0) {

row = 0;}col += deltay;if (col < 0) {

col = 0;}

// replacer le groupe de boutonstable.setWidget(row, col, buttonPanel);

}}

Page 200: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

186 Aller plus loin avec GWT

Exemple d’appel à un service RPC (chapitre 5)

Code source de GwtChap52.java

package oge.gwt.chap52.client;

import com.google.gwt.core.client.EntryPoint;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.event.dom.client.KeyCodes;import com.google.gwt.event.dom.client.KeyUpEvent;import com.google.gwt.event.dom.client.KeyUpHandler;import com.google.gwt.user.client.rpc.AsyncCallback;import com.google.gwt.user.client.rpc.ServiceDefTarget;import com.google.gwt.user.client.ui.Button;import com.google.gwt.user.client.ui.DialogBox;import com.google.gwt.user.client.ui.HTML;import com.google.gwt.user.client.ui.Label;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.user.client.ui.TextBox;import com.google.gwt.user.client.ui.VerticalPanel;

/*** Example: appel du service RPC d’addition*/public class GwtChap52 implements EntryPoint {

// Le point d’entréepublic void onModuleLoad() {

// créer les widgetsfinal Button sendButton = new Button("=");final TextBox op1Field = new TextBox();final TextBox op2Field = new TextBox();final TextBox resultField = new TextBox();op1Field.setText("1");op2Field.setText("2");

// récupérer le conteneur et y ajouter les widgetsRootPanel container = RootPanel.get("container");container.add(op1Field);container.add(new HTML(" + "));container.add(op2Field);container.add(sendButton);container.add(resultField);

// donner le focus au premier champ texteop1Field.setFocus(true);op1Field.selectAll();

// Handler pour événements clic-souris et appui sur une toucheclass MyHandler implements ClickHandler, KeyUpHandler {

Page 201: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 187

// appelé lorsque l’utilisateur clique sur le bouton "="public void onClick(ClickEvent event) {

// effectuer l’appel au serveursendToServer();

}

// appelé lorsque l’utilisateur appuie sur Enter// dans un champ textepublic void onKeyUp(KeyUpEvent event) {

if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {// effectuer l’appel au serveursendToServer();

}}

/** Méthode qui récupère les paramètres, effectue*/private void sendToServer() {

sendButton.setEnabled(false);long x = Long.parseLong(op1Field.getText());long y = Long.parseLong(op2Field.getText());

/*** Create a remote service proxy to talk* to the server-side Greeting service.*/final AdditionServiceAsync addService =

GWT.create(AdditionService.class);

addService.additionner(x, y, new AsyncCallback<Long>() {public void onFailure(Throwable caught) {

// échecresultField.setText(caught.toString());

}

public void onSuccess(Long result) {// succèsresultField.setText("" + result);

}});

}}

// Add a handler to send the name to the serverMyHandler handler = new MyHandler();sendButton.addClickHandler(handler);op1Field.addKeyUpHandler(handler);op2Field.addKeyUpHandler(handler);

}}

Page 202: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

188 Aller plus loin avec GWT

Exemple de mise en œuvre du mécanisme d’historique (chapitre 8)

Code source de GwtHistory.java

package oge.gwt.history.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.event.logical.shared.SelectionEvent;import com.google.gwt.event.logical.shared.SelectionHandler;import com.google.gwt.event.logical.shared.ValueChangeEvent;import com.google.gwt.event.logical.shared.ValueChangeHandler;import com.google.gwt.user.client.History;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.user.client.ui.Tree;import com.google.gwt.user.client.ui.TreeItem;

public class GwtHistory implements EntryPoint {

/*** Le point d’entrée*/

public void onModuleLoad() {//

// construction de l’arbre//TreeItem racine = new TreeItem("Noeud Racine");{

TreeItem n1 = new TreeItem("Noeud 1");{

TreeItem n11 = new TreeItem("Noeud 1.1");n11.addItem(new TreeItem("Noeud 1.1.1"));n11.addItem(new TreeItem("Noeud 1.1.2"));n1.addItem(n11);

}{

TreeItem n12 = new TreeItem("Noeud 1.2");n12.addItem(new TreeItem("Noeud 1.2.1"));n12.addItem(new TreeItem("Noeud 1.2.2"));n1.addItem(n12);

}racine.addItem(n1);

}{

TreeItem n2 = new TreeItem("Noeud 2");

n2.addItem(new TreeItem("Noeud 2.1"));n2.addItem(new TreeItem("Noeud 2.2"));racine.addItem(n2);

}

final Tree tree = new Tree();tree.addItem(racine);

//// ajout SelectionHandler//tree.addSelectionHandler(new SelectionHandler<TreeItem>() {

Page 203: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 189

public void onSelection(SelectionEvent<TreeItem> event) {// construire le token sur base du hashcode du texte// du noeud sélectionnéTreeItem selectedItem = event.getSelectedItem();String token =Long.toHexString(selectedItem.getText().hashCode());// créer une entrée d’historiqueHistory.newItem(token);

}});

//// ajout du handler historique//History.addValueChangeHandler(new ValueChangeHandler<String>() {

public void onValueChange(ValueChangeEvent<String> event) {// récupérer le tokenString token = event.getValue();// tenter de trouver le noeud corespondantTreeItem item = findNode(tree, token);if (item != null) {

// noeud trouvé: le sélectionnertree.setSelectedItem(item);// s’assurer que sa branche est déployéeensureExpanded(item);

}}

});

RootPanel.get().add(tree);}

/*** S’assurer que le noeud spécifié est visible (c’est-à-dire* que son parent et tous ses ascendants sont déployés)*/protected void ensureExpanded(TreeItem item) {

TreeItem parentItem = item.getParentItem();if (parentItem != null) {

parentItem.setState(true);ensureExpanded(parentItem);

}}

/*** Retourne le noeud de l’arbre correspondant à l’identifiant spécifié,* ou null si pas trouvé*/private TreeItem findNode(Tree tree, String token) {

for (int i = 0; i < tree.getItemCount(); i++) {TreeItem child = tree.getItem(i);TreeItem target = findNode(child, token);if (target != null) {

return target;}

}return null;

Page 204: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

190 Aller plus loin avec GWT

}

/*** Retourne le noeud correspondant à l’identifiant spécifié parmi le* noeud passé en paramètre et ses descendants, null si pas trouvé*/

private TreeItem findNode(TreeItem item, String token) {if (match(item, token)) {

return item;}for (int i = 0; i < item.getChildCount(); i++) {

TreeItem child = item.getChild(i);TreeItem target = findNode(child, token);if (target != null) {

return target;}

}return null;

}

/*** Retourne true si et seulement si le noeud spécifié correspond à* l’identifiant. Cette implémentation utilise le hashcode* du texte du noeud*/

private boolean match(TreeItem item, String token) {return Long.toHexString(item.getText().hashCode()).equals(token);

}}

Page 205: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 191

Appel à un service web JSON (chapitre 9)

Code source de JSONRequestHelper.java (classe utilitaire)

package oge.gwt.chap95.client.util;

import com.google.gwt.core.client.JavaScriptObject;

public class JSONRequestHelper {

public interface JSONResponseHandler {public void onResponseReceived(JavaScriptObject json);

}

/*** Effectue un appel à un web service JSON. Le web service doit* supporter les options "JSON in script" et "JavaScript callback".** @param url L’URL du service à appeler, moins le nom du callback.* Le nom du callback sera concaténé à la fin de l’URL; celle-ci* devra donc se terminer par un paramètre du type "callback=".* @param handler une instance de JSONResponseHandler dont* la méthode onResponseReceived* sera appelée après réception du résultat.*/public static void get(String url, JSONResponseHandler handler) {

// Construire un nom de callback propre au handler.// Ceci permet de gérer des situations// où plusieurs appels simultanés sont faits// avec des handlers différents.String callbackName = "callback" + handler.hashCode();get(url + callbackName, callbackName, handler);

}

/*** Méthode native JSNI qui effectue la manipulation du DOM.* @param url L’URL complète (y compris le callback)* @param callbackName Le nom du callback* @param handler Le handler client à appeler*/private native static void get(String url, String callbackName,

JSONResponseHandler handler) /*-{callback = function(j) {[email protected].

JSONRequestHelper$JSONResponseHandler::onResponseReceived(Lcom/google/gwt/core/client/JavaScriptObject;)(j);

};$wnd[callbackName] = callback;

var script = $wnd.document.createElement("script");script.setAttribute(‘‘type’’, ‘‘text/javascript’’);script.setAttribute(‘‘src’’, url);$wnd.document.getElementsByTagName(‘‘head’’)[0].appendChild(script);

}-*/;

}

Page 206: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

192 Aller plus loin avec GWT

Contenu de la page HTML hôte

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>

<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>JSONP</title><script type="text/javascript" language="javascript"

src="gwtchap95/gwtchap95.nocache.js"></script></head>

<body><h1>JSON web service demo</h1>

<table align="center"><tr><td colspan="2" style="font-weight:bold;">

URL complète du service web:</td></tr><tr><td id="nameFieldContainer"></td><td id="sendButtonContainer"></td>

</tr><tr><td colspan="2" style="font-weight:bold;">Résultat :</td></tr><tr><td colspan="2" id="result"></td></tr>

</table></body>

</html>

Code source de GwtChap95.java (client)

package oge.gwt.chap95.client;import oge.gwt.chap95.client.util.JSONRequestHelper;import oge.gwt.chap95.client.util.JSONRequestHelper.JSONResponseHandler;import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.JavaScriptObject;import com.google.gwt.event.dom.client.ClickEvent;import com.google.gwt.event.dom.client.ClickHandler;import com.google.gwt.event.dom.client.KeyUpEvent;import com.google.gwt.event.dom.client.KeyUpHandler;import com.google.gwt.json.client.JSONObject;import com.google.gwt.user.client.ui.Button;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.user.client.ui.TextArea;import com.google.gwt.user.client.ui.TextBox;

public class GwtChap95 implements EntryPoint {

private TextBox urlField;private TextArea resultArea;

/*** Le point d’entrée*/

Page 207: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 193

public void onModuleLoad() {// le champ URLurlField = new TextBox();urlField.setWidth("100%");urlField.setText("http://www.google.com/calendar/feeds/

[email protected]/public/full?alt=json-in-script&callback=");

// le bouton d’envoifinal Button sendButton = new Button("Envoyer");sendButton.addStyleName("sendButton");

// la zone qui affichera le résultatresultArea = new TextArea();resultArea.setVisibleLines(20);resultArea.setCharacterWidth(80);

// Ajoute les widgets au RootPanelRootPanel.get("nameFieldContainer").add(urlField);RootPanel.get("sendButtonContainer").add(sendButton);RootPanel.get("result").add(resultArea);

// Focus dans le champ URLurlField.setFocus(true);urlField.selectAll();

// Handler pour le bouton et le TextFieldclass MyHandler implements ClickHandler, KeyUpHandler {

public void onClick(ClickEvent event) {fetchJSON();

}public void onKeyUp(KeyUpEvent event) {

fetchJSON();}

}

MyHandler handler = new MyHandler();sendButton.addClickHandler(handler);urlField.addKeyUpHandler(handler);

}

/*** Cette méthode effectue l’envoi de la requête JSON et affiche* le résultat dans la TextArea.*/private void fetchJSON() {

String url = urlField.getText();JSONRequestHelper.get(url, new JSONResponseHandler() {

public void onResponseReceived(JavaScriptObject json) {// convertir l’objet en JSONObjectJSONObject jsonValue = new JSONObject(json);// convertir en texteString result = jsonValue.toString();// afficher dans la TextArearesultArea.setText(result);

}});

}}

Page 208: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

194 Aller plus loin avec GWT

Exemple d’utilisation de l’API Google Gears (chapitre 11)

Code source de GwtGearsDemo.java

package oge.gwt.chap11.client;

import java.util.ArrayList;import java.util.Date;import java.util.List;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.event.dom.client.ClickEvent;import com.google.gwt.event.dom.client.ClickHandler;import com.google.gwt.event.dom.client.KeyCodes;import com.google.gwt.event.dom.client.KeyPressEvent;import com.google.gwt.event.dom.client.KeyPressHandler;import com.google.gwt.gears.client.Factory;import com.google.gwt.gears.client.GearsException;import com.google.gwt.gears.client.database.Database;import com.google.gwt.gears.client.database.DatabaseException;import com.google.gwt.gears.client.database.ResultSet;import com.google.gwt.user.client.Window;import com.google.gwt.user.client.ui.Button;import com.google.gwt.user.client.ui.Grid;import com.google.gwt.user.client.ui.HorizontalPanel;import com.google.gwt.user.client.ui.RootPanel;import com.google.gwt.user.client.ui.TextBox;import com.google.gwt.user.client.ui.VerticalPanel;

/*** Démonstration de Gears Database*/public class GwtGearsDemo implements EntryPoint {

private Database db;private Grid grid;private TextBox msgBox;

public void onModuleLoad() {

// Créer la base si elle n’existe pastry {

db = Factory.getInstance().createDatabase();db.open("gears-database-demo");db.execute("create table if not exists demo (

Message text, Timestamp int)");} catch (GearsException e) {

Window.alert(e.toString());}

// créer les composants graphiquesVerticalPanel panel = new VerticalPanel();panel.setSpacing(15);HorizontalPanel hPanel = new HorizontalPanel();msgBox = new TextBox();Button sendBtn = new Button("OK");Button clearBtn = new Button("Effacer tout");

Page 209: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 195

hPanel.add(msgBox);hPanel.add(sendBtn);hPanel.add(clearBtn);

panel.add(hPanel);

grid = new Grid();grid.setBorderWidth(1);panel.add(grid);

RootPanel.get("gears").add(panel);

// ajouter les handlersmsgBox.addKeyPressHandler(new KeyPressHandler() {

public void onKeyPress(KeyPressEvent event) {if (event.getCharCode() == KeyCodes.KEY_ENTER) {

insertEntry();}

}});sendBtn.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {insertEntry();

}});clearBtn.addClickHandler(new ClickHandler() {

public void onClick(ClickEvent event) {clearAll();updateMessages();

}});

// initialiser la listeupdateMessages();

}

// effacer tous les messagesprivate void clearAll() {

try {db.execute("delete from demo");

} catch (DatabaseException e) {Window.alert(e.toString());

}}

// mettre à jour la liste des messages affichéeprivate void updateMessages() {

// Récupérer les entrées existantesList<String> messages = new ArrayList<String>();List<String> timestamps = new ArrayList<String>();try {

ResultSet rs = db.execute("select * from demo orderby Timestamp");

for (int i = 0; rs.isValidRow(); ++i, rs.next()) {messages.add(rs.getFieldAsString(0));timestamps.add(rs.getFieldAsString(1));

Page 210: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

196 Aller plus loin avec GWT

}rs.close();

} catch (DatabaseException e) {Window.alert(e.toString());

}

// mettre à jour la grillegrid.resize(timestamps.size() + 1, 2);grid.setText(0, 0, "Date");grid.setText(0, 1, "Message");for (int row = 0; row < timestamps.size(); ++row) {

Date date = new Date(Long.valueOf(timestamps.get(row)));grid.setText(row + 1, 0, date.toString());grid.setText(row + 1, 1, messages.get(row));

}

}

// ajouter un message dans la base localeprivate void insertEntry() {

String msg = msgBox.getText();try {

db.execute("insert into demo values (?, ?)", new String[] {msg,Long.toString(System.currentTimeMillis()) });

updateMessages();msgBox.setText("");

} catch (DatabaseException e) {Window.alert(e.toString());

}

}}

Page 211: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Annexes 197

Exemple d’utilisation d’UiBinderpour créer un widget composite (chapitre 12)

Fichier de description pour UiBinder (SexeRadio2.ui.xml)

<gwt:UiBinder xmlns:ui=’urn:ui:com.google.gwt.uibinder’xmlns:gwt=’urn:import:com.google.gwt.user.client.ui’>

<gwt:HorizontalPanel><gwt:Label text="Sexe :" /><gwt:VerticalPanel>

<gwt:RadioButton name=’sexeradio’ text=’M’ui:field=’maleRadio’ />

<gwt:RadioButton name=’sexeradio’ text=’F’ui:field=’femaleRadio’ />

</gwt:VerticalPanel></gwt:HorizontalPanel>

</gwt:UiBinder>

Code source de SexeRadio2.java

package oge.gwt2.uibinder.client;

import com.google.gwt.core.client.GWT;import com.google.gwt.event.dom.client.ClickEvent;import com.google.gwt.uibinder.client.UiBinder;import com.google.gwt.uibinder.client.UiField;import com.google.gwt.uibinder.client.UiHandler;import com.google.gwt.uibinder.client.UiTemplate;import com.google.gwt.user.client.ui.Composite;import com.google.gwt.user.client.ui.Panel;import com.google.gwt.user.client.ui.RadioButton;

public class SexeRadio2 extends Composite {

@UiTemplate("SexeRadio2.ui.xml")interface MyUiBinder extends UiBinder<Panel, SexeRadio2> {}

private static final MyUiBinder binder = GWT.create(MyUiBinder.class);

public SexeRadio2() {final Panel panel = binder.createAndBindUi(this);initWidget(panel);

}

@UiFieldRadioButton maleRadio;

@UiFieldRadioButton femaleRadio;

@UiHandler("maleRadio")void maleClicked(ClickEvent event) {

GWT.log("C’est un garçon !", null);}

Page 212: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

198 Aller plus loin avec GWT

@UiHandler("femaleRadio")void femaleClicked(ClickEvent event) {

GWT.log("C’est une fille !", null);}

public boolean isM() {return maleRadio.getValue();

}

public boolean isF() {return femaleRadio.getValue();

}}

Page 213: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Webographie

GWT : le site principal de Google

http://code.google.com/webtoolkit

Le plugin Google pour Eclipse

http://code.google.com/eclipse

Les groupes de discussion consacrés à GWT (Google Groups)

http://groups.google.com/group/Google-Web-Toolkit

Code source des exemples de ce livre (hébergé sur Google Code)

http://code.google.com/p/livre-gwt

Blog de l’auteur

http://blog.gerardin.info

onGWT : informations quotidiennes sur GWT (en anglais)

http://www.ongwt.com

Le blog Google sur GWT (an anglais)

http://googlewebtoolkit.blogspot.com/

Page 214: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation
Page 215: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Index

A

AbsolutePanel 61AJAX 9Ant 35API 152appel de procédure à distance (RPC) 71applet 6application

point d’entrée 20serveur d’applications 36

arborescence 117asynchronisme 72Atom 126

B

bibliothèquede composants 139Ext JS 139Ext-GWT 145GWT-ext 139MyGWT 145SmartGWT 149utilitaire 152

binding 152bootstrap 38breakpoint 32Button 44, 136

C

callback 72, 166CheckBox 46checked (exception) 84classe

Composite 134Client-side Scripting 7ClientBundle 178code

compiler 36langue 97pays 97

code splitting 166compilateur GWT 37compiler 36

compte-rendu (SOYC) 168Component Library 151Composite 134CSS (styles) 42cycle de développement 39

D

data binding 145, 148date

formatage 105DatePicker 47DateTimeFormat 106

Page 216: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

202 GWT

débug 39DeckPanel 63Deferred Binding 110déploiement 81DialogBox 58DisclosurePanel 66Dockpanel 65DOM (Document Object Model) 8

XML 124dossier

war 18dynamique

interface 41

E

Eclipse 14, 15Google Plugin for Eclipse 14installation 16JEE 16projet 22

Entity JavaBeans (EJB) 36Environnement de développement

intégré (IDE) 10, 38environnement de production 81événement 43exception 33, 83

contrôlée 84Ext JS 139Ext-GWT 145

F

FlexTable 66FlowPanel 63flux

Atom 126formatage

date 105nombre 105

fragment (URL) 116

G

Gears 153gestion

exception 33historique 51, 115

Google Plugin 14, 17Google Web Toolkit (GWT)

compilateur 37historique 10installation 15module 21version 2.0 159

Grid 66Gwittir 152GWT Component Library 151GWT Incubator 150GWT Server Library 152GWT Widget Library 151GWT-ext 139GWTiger 151

H

handler 43historique

gestion 51, 115jeton 116

HorizontalPanel 62HorizontalSplitPanel 64hosted mode 31, 35, 76

Out Of Process Hosted Mode(OOPHM) 161

hosted mode 13hostname 4HTTP (module) 122Hyperlink 51hypertexte 3

I

i18n 89Incubator 150

Page 217: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Index 203

Integrated Development Environment(IDE) 10, 38

interfaceConstants 91ConstantsWithLookup 103Messages 104

interface homme-machine (IHM) 41internationalisation 89

statique 90, 112

J

Java 6exeption 83sérialisation 34

Java Runtime Environment (JRE) 32classes 33

JavaScript 7AJAX 9mono-thread 33XmlHttpRequest 9

JEE (Eclipse) 16jeton d’historique 116Jetty 36, 76JSNI (JavaScript Native Interface) 14,

107, 129, 136JSON 121, 126JSP 7

L

laison différée 110langue 89layout 60, 144ListBox 51locale 89, 96

M

MenuBar 53méthode

JSNI 14MIME 5

modedebug 39hôte 13, 31, 35, 76, 161web 36

module 21HTTP 122I18N 90

mono-thread 33MVC (Model-View-Controller) 149MyGWT 145

N

navigateurversion 110

nombreformatage 105

normeServlet Java 72

NumberFormat 105

O

Out Of Process Hosted Mode (OOPHM)161

P

panel 43, 60AbsolutePanel 61DeckPanel 63DisclosurePanel 66Dockpanel 65FlexTable 66FlowPanel 63Grid 66HorizontalPanel 62HorizontalSplitPanel 64layout 60PopupPanel 61RootPanel 60StackPanel 62TabPanel 66VerticalPanel 62

Page 218: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

204 GWT

VerticalSplitPanel 64paramètres régionaux 97PasswordTextBox 49PHP 6Plain Old Java Object (POJO) 152plate-forme 37plugin 15point

d’arrêt 32d’entrée 20de séparation 166

PopupPanel 61proxy serveur 131PushButton 45

Q

query string 4

R

RadioButton 45Remote Procedure Call (RPC) 71, 151,

152asynchronisme 72

requête HTTP 121RichtextArea 57RootPanel 60

S

Same Origin Policy (SOP) 122schema 4sérialisation 34, 82Server Library 152serveur 187

appel 77code 71communication 71d’applications intégré 36déploiement 18, 76Jetty 36proxy 131Tomcat 36

servlet 7Servlet Java 72

SmartGWT 149split point 166StackPanel 62Story Of Your Compile (SOYC) 168style 42SuggestBox 54

T

TabPanel 66TextArea 50TextBox 49ToggleButton 48token (history) 116Tomcat 36Tree 53, 117type

MIME 5

U

UiBinder 174unchecked (exception) 84URL 4

fragment 116hostname 4query string 4schema 4

V

version 110, 159VerticalPanel 62VerticalSplitPanel 64

Wwar

(dossier) 18Web

historique 3hypertexte 3

Page 219: GWT - Annonces Gratuites avec Vidéo et Flux Twitter en ... · En créant GWT, Google ouvre une nouvelle ère du développement et rend accessible à tous les développeurs la réalisation

Index 205

web mode 31web service 122, 128webAppCreator 35widget 42, 176

Button 44, 136CheckBox 46créer 133DatePicker 47DialogBox 58GWT Component Library 151GWT Widget Library 151Hyperlink 51implémenter 135ListBox 51MenuBar 53panel 60PasswordTextBox 49

PushButton 45RadioButton 45RichtextArea 57sous-classer 134SuggestBox 54TextArea 50TextBox 49ToggleButton 48Tree 53widget-fils 60

Widget Library 151

X

XML 124AJAX 9DOM 124XmlHttpRequest 9