TP GWT JDEV 2015

160
T7.A02 JDEV 2015 François ANDRE Guillaume BRISSEBRAT Alexandre JOURNAUX OMP, INRA

Transcript of TP GWT JDEV 2015

Page 1: TP GWT JDEV 2015

T7.A02JDEV 2015

François ANDREGuillaume BRISSEBRATAlexandre JOURNAUX

OMP, INRA

Page 2: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LICENCE

Le contenu de cette présentation est publié sous la licence :

Creative Commons Attribution 4.0 International License

La copie de cette présentation est autorisée sous réserve du respectdes conditions de la licence (creativecommons.org/licenses/by/4.0/).

2

Page 3: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CODE SOURCE

Le code source du TP est disponible à l’adresse suivante:

https://github.com/francoisandre/gwtjdev2015

Afin de pouvoir repartir sur une situation propre sur un exercice plusieursbranches correspondant à chaque fin d’exercice sont mise à disposition.Elles sont signalées en fin chaque branche correspond à la fin d’un exercice.Cela permet de pouvoir passer à un nouvel exercice.

Les branches sont signalées de la manière suivante:

NomDeLaBranche

3

Page 4: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MACHINE VIRTUELLE

Une machine virtuelle de type VirtualBox comportant les outilsnécessaires et le code source du TP est disponible à l’adressesuivante:

http://jdev2015.sedoo.fr/Stagiaire%20GWT-c.ova

Afin de récuperer le code du TP effectuez la procédure suivante :

I Ouvrir EclipseI Sélectionner File > Import...I Dans la liste des types de projets, séléctionner Git > Projects from Git et appuyer sur

NextI Séléctionner Existing local repository et appuyer sur NextI Dans la liste des dépots Git, séléctionner git /home/user/git/.git et appuyer sur NextI Dans l’étape relative au Wizard appuyer directement sur NextI Appuyer sur Finish

4

Page 5: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

SOMMAIRE

1. Introduction

2. Architecture

3. Premiere application

4. Creation de l’interfacegraphique

5. Bus d’evenements

6. Cinematique de l’application

7. Communication client-serveur

8. Conclusion

5

Page 6: TP GWT JDEV 2015

INTRODUCTION

Page 7: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

QUELQUES QUESTIONS...

I Comment faire une Single Page Application ?I Où doit se situer un traitement ?I Android ou iOS ?I Des gens utilisent-ils encore IE6 ?I Comment économiser les ressources ?I Comment faire une boucle en Javascript ?I Comment déboguer ou lister les appels d’une fonction en

Javascript ?I Pourquoi ne puis-je pas faire du Swing ?I Le client-serveur, ça avait son charme, non ?I Pourquoi mon application n’est-elle toujours pas finie ?I C’est pas plus rapide en PHP ?I Google n’a-t-il pas arrêté GWT ?

7

Page 8: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

FIABLILITÉ DE LA CIBLE CSS+HTML5+JAVASCRIPT

8

Page 9: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE RÉPONSE POSSIBLE

GWT

9

Page 10: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IDÉE SIMPLE

Coder la partie cliente en JavaLa compiler en JavaScript

10

Page 11: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AVANTAGES PRINCIPAUX

Intégré dans l’écosystème JEERelié à l’écosystème HTML/Javascript

11

Page 12: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

REPÈRE HISTORIQUES

Chronologie succincte :

I 2006 v1.0

I ...

I 2009 v2.0

I ...

I Janvier 2014 v2.6.0

I Novembre 2014 v2.7.0

Futur

I Évolutions WEB : HTML5, W3C Web Components ...

I Évolutions Java : Support Java 8 ...

I Évolutions GWT : Integration Javascript ...

12

Page 13: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PLUS D'INFORMATIONS

I Site officiel : http://www.gwtproject.org/

I Démonstration officielle :http://samples.gwtproject.org/samples/Showcase/Showcase.html

I Communautéhttps://groups.google.com/forum/#!forum/google-web-toolkithttps://plus.google.com/communities/116543000751323604177

I Conférences en ligne :GWT Create (http://gwtcreate.com/)Google I/O (chaîne Youtube)

I Blogs :Gwt Daily (http://www.gwtdaily.com/)Sami Jabber (http://www.samijaber.com/)

I Tutoriels :http://courses.coreservlets.com/Course-Materials/gwt.html

13

Page 14: TP GWT JDEV 2015

ARCHITECTURE

Page 15: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ELÉMENTS MIS ENŒUVRE

15

Page 16: TP GWT JDEV 2015

TWITTER BOOTSTRAP

Page 17: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

TWITTER BOOTSTRAP

Description : Collection d’outils HTML/CSS/JavascriptObjectif : Compenser l’aspect brut des composants GWT

I Rendu moderne

I Site webadaptatif (RWD)

I GrandePopularité

17

Page 18: TP GWT JDEV 2015

SPRING FRAMEWORK

Page 19: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

SPRING FRAMEWORK

Description : Framework Java permettant la mise en place d’unconteneur légerObjectif : Simplification de l’architecture et fiabilisation du code

I Inversion decontrôle (IoC)

I Bibliothèquescomplémentaires(accès auxdonnées, ...)

19

Page 20: TP GWT JDEV 2015

JPA : JAVA PERSISTENCE API

Page 21: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

JPA : JAVA PERSISTENCE API

Description : API officielle de Mapping Objet-SGBDObjectif : Simplifier la mise en œuvre de la persistance

I Définition du mapping via annotation

I Interrogation via JPQL

21

Page 22: TP GWT JDEV 2015

MAVEN

Page 23: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MAVEN

Description : Moteur de productionObjectif : Fiabilise les étapes clés du développement (compilation,test, génération, livraison,...)

I Le fichier pom.xml : configuration globale du projetI Arborescence

/src Sources du projet/src/main Partie principale/src/main/java Code source/src/main/resources Fichier de ressources (images, config, ...)/src/main/webapp Webapp du projet/src/test Partie test/src/test/java Code source des tests/src/test/resources Fichiers de ressources des tests/target Fichiers produits (classes, .war, .jar)

I Compatibilité avec les outils d’intégration continue (Jenkins...)23

Page 24: TP GWT JDEV 2015

ECLIPSE

Page 25: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ECLIPSE

Description : Environnement de développement intégré (EDI)Objectif : Édition des sources, lien avec le SCM, débogage

GWT ne nécessite pas d’EDI particulier. D’autres EDI (IntelliJ,Netbeans, vi) peuvent être utilisés.

L’équipe Google fournit un module (plugin) pour Eclipse proposantcertaines fonctionnalités utiles :

I Génération

I Validation

I ...

Remarque:

I Distribution privilégiée : Eclipse IDE for Java EE Developers25

Page 26: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PLUGIN GWT (NAVIGATEUR)

I Classical dev modeJusqu’à la version 2.6.0, le développement GWT - Dev Mode - reposesur un module installé sur le navigateur (Chrome, Firefox, IE, Safari).

Ce mode est contraignant pour les développeur de GWT pour lesraisons suivantes :

Le nombre de navigateursLes API propriétaires sous jacentes

De plus, lorsque la taille de l’application augmente le temps derafraichissement devient bloquant.

I Super dev modeDepuis la version 2.4.0 il est progressivement remplacé par le SuperDev Mode qui permet de débugger dans les navigateurs supportant lestandard SourceMaps (Chrome, Firefox).Le plugin SDBG permet de conserver un débuggage dans Eclipse.

26

Page 27: TP GWT JDEV 2015

PREMIÈRE APPLICATION

Page 28: TP GWT JDEV 2015

EXERCICE 1 : GÉNÉRATION D'UNSQUELETTE APPLICATIF

Page 29: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PRÉREQUIS LOGICIEL

Prérequis:

I JVM (1.7 conseillée)I Maven / Ant

I Eclipse avec les plugins

EgitM2EPlugin GWT (via Eclipse Market Place)SDBG (update site: http://sdbg.github.io/p2)StartExplorer (via Eclipse Market Place)

I SDK GWT (2.7.0)I Chrome (avec SourceMap enabled)

29

Page 30: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GÉNÉRATION D'UN SQUELETTE APPLICATIF

Utilisation de webAppCreator (utilitaire fourni dans le SDK)

Etape 1 : Génération squelette

/home/user/Développement/gwt-2.7.0/webAppCreator -noant -maven -XnoEclipse

fr.jdev.atelier.MonApplication

Etape 2 : Import dans Eclipse

Import... > Maven > Existing Maven Projects

Etape 3 : Modification fichier pom.xml

Ajouter la version <version>$gwtVersion</version> dans les dépendances<groupId>com.google.gwt</groupId> <dependency> :...<dependency><groupId>com.google.gwt</groupId><artifactId>gwt-servlet</artifactId><version>$gwtVersion</version><scope>runtime</scope></dependency>...

30

Page 31: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GÉNÉRATION D'UN SQUELETTE APPLICATIF

Etape 4 : Modifications des propriétés du projet

Google > Web toolkit : cocher Use Google Web ToolkitGoogle > Web application :

I Cocher This project has a WAR directory

I Dans la zone de saisie WAR directory indiquer src/main/webapp

I Décocher Launch and deploy... si nécessaire

FinExercice1

31

Page 32: TP GWT JDEV 2015

EXPLORATION DU SQUELETTE

Page 33: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXPLORATION DU SQUELETTE

Architecture Maven classique

I /src/main/java

I /src/main/resources

I /src/main/webapp

I ...

Architecture GWT classique

Package client Classes de la partie cliente (⇒ Javascript)

Package sharedClasses communes client & serveur(⇒ Javascript & Java)

Package serverClasses de la partie serveur(⇒ Application JEE standard)

33

Page 34: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CONTRAINTES PACKAGE CLIENT & SHARED

I Les classes doivent utiliser/étendre le JDK émulé par GWT(http://www.gwtproject.org/doc/latest/RefJreEmulation.html)Exemples :

Autorisé: Object, HashMap, ArrayList,com.google.common.base.Strings (Guava)...Interdit : File, StringUtils (commons-lang), ...

I Les classes transitant entre client et serveur doivent être

sérialisables:

• implémenter java.io.Serializable• implémenter com.google.gwt.user.client.rpc.IsSerializable

des beans:• Constructeur vide• Getters et Setters

34

Page 35: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DESCRIPTEUR DU MODULE: MONAPPLICATION.GWT.XML

I RôlePilotage de l’application

I Positionau dessus du package client

I ContenuNom du module <module>Point d’entrée<entry-point class=’fr.jdev.atelier.client.MonApplication’ />

Autres modules à importer : <inherits>Répertoires : <source>Paramètres divers: langues...Remplacement dynamique des classes

<replace-with class="fr.sedoo.sssdata.client.ClientFactoryImpl"><when-type-is class="fr.sedoo.sssdata.client.ClientFactory"/>

</replace-with>

35

Page 36: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CONTENEUR HTML MONAPPLICATION.HTML

I RôleChargement de l’application

I PositionDans le répertoire webapp

I ContenuPage HTML classique (js, css, balises HTML...)Chargement du module

<script type="text/javascript" language="javascript"src="monapplication/monapplication.nocache.js"></script>

Remarque: le script nocache.js charge la compilation adéquatedu module :

La plus récenteCorrespondant au navigateur du client et à sa langue

36

Page 37: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

COMPILATION ET PERMUTATIONS

Lors de la compilation Javascript, GWT génère une tradution pourchaque couple

I moteur de navigateur supporté (6)I langue indiquée dans le descripteur de module

Les permutations sont une des nombreuses optimisations fournies parGWT.

37

Page 38: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ENTRY POINT

I RôleÉquivalent de main dans les application Java

I PositionDans le package clientConformément au fichier gwt.xml

I ContenuImplémente com.google.gwt.core.client.EntryPoint↪→ public void onModuleLoad() ;

• Construit les éléments de l’interface utilisateur• Optionnellement, supprime certains éléments du conteneur HTML

Exemple : suppression du contenu de l’élément d’identifiant loadingMessage

RootPanel loadingMessage = RootPanel.get("loadingMessage");DOM.setInnerHTML(loadingMessage.getElement(), "");

• Ajoute l’interface utilisateur dans le conteneur HTMLExemple : En vidant completement le conteneur HTML

Label myLabel = new Label("Hello JDEV");RootPanel.get().clear();RootPanel.get().add(myLabel);

38

Page 39: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AUTRES FICHIERS REMARQUABLES

I Configuration Maven/pom.xml

I Configuration application web/src/main/webapp/WEB-INF/web.xml

39

Page 40: TP GWT JDEV 2015

EXERCICE 2 : EXÉCUTION ETDÉBOGAGE

Page 41: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LANCEMENT DE L'APPLICATION

I Le lancement de l’application se fait classiquement via les menusDebug As ou Run As

I Le moteur de lancement à utiliser est Web Application ou WebApplication (GWT Super Dev Mode)

41

Page 42: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LANCEMENT DE L'APPLICATION

Lors du lancement, deux applications sont exécutées dans l’ordresuivant :

I Le serveur de complitation Java →Javascript

...The code server is ready at http://127.0.0.1:9876...

I L’application proprement dite. Celle-ci est utilisable lors que son URL s’affiche dansl’onglet Development

42

Page 43: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

TEST DE L'APPLICATION

I Le lancement de l’URL déclenche la compilation Java→Javascript.

I Une fois compilée l’application apparait normalement

43

Page 44: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

TEST DE L'APPLICATION

I RemarquesLa première compilation suivant un démarrage de l’application estlongueLes autres compilations sont plus rapides car incrémentales (neportent que sur les fichiers modifiés entre temps)Le code java peut être vu via Chrome (via la technologieSourceMaps)

44

Page 45: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DEBOGAGE AVEC LE PLUGIN ECLIPSE SDBG

I SDBG permet d’intercepter de piloter le débogage SourceMapsdans Eclipse

Etape 1 : Création d'un lanceur chrome

I Ouvrir la fenêtres des lanceurs de débogage (Debug configurations...)

I Sélectionner Launch Chrome

I Cliquer sur le bouton droit et sélectionner New

I Dans la fenêtre qui s’ouvre indiquer les valeurs suivantes :

Name : Mon Application SDBGURL : http://127.0.0.1:8888/MonApplication.htmlProject : sélectionner le projet MonApplication

Remarque : Dans l’onglet Common on peut cocher l’option Debug du bloc Display infavorites menu

I Cliquer sur Apply puis sur DebugL’application doit être lancée auparavant

45

Page 46: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DEBOGAGE AVEC LE PLUGIN ECLIPSE SDBG

Etape 2 : Mise en place d'un point d'arrêt

I Dans la classe FieldVerifier positionner un point d’arrêt en début de la méthodeisValidName

I Dans l’application cliquer sur Send

Le point d’arrêt va se déclencher deux fois

Côté client : suite à l’appel de sendNameToServerCôté serveur : suite à l’appel de greetServer

I Remarques :le plugin SDBG est en amélioration permanente

• Pour la gestion du rechargement à chaud• Pour l’affichage des contenus des variables

le plugin SDBG est désactivé lorsque l’inspecteur Chrome estactivé.

46

Page 47: TP GWT JDEV 2015

CRÉATION DE L'INTERFACEGRAPHIQUE

Page 48: TP GWT JDEV 2015

COMPOSANTS DE BASES

Page 49: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

COMPOSANTS DE BASE

GWT propose un certain nombre de composants de base pourconstruire les interfaces:

I Widgets élémentaires: boutons, zones de texte, cases à cocher...

I Panneaux de positionnement (similaires à Swing): panneauxhorizontaux, verticaux, à onglets...

Comme en Swing, ces éléments sont des classes Java et secombinent afin de créer l’interface souhaitée.

49

Page 50: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

WIDGETS ÉLÉMENTAIRES

I Étendent com.google.gwt.user.client.ui.Widget

Exemples :

TextBox

TextArea

Button

RadioButtonCheckBox

DatePicker, CellList...50

Page 51: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PANNEAUX DE POSITIONNEMENT

I Panneaux classiques(étendent com.google.gwt.user.client.ui.Panel)

Exemples :

HorizontalPanel

VerticalPanel

FlowPanel

HTMLPanelPermet de mixer des balises HTML et des com-posants GWT

Remarque: les panneaux héritent aussi de Widget51

Page 52: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PANNEAUX DE POSITIONNEMENT

I Panneaux dynamiques(implémententcom.google.gwt.user.client.ui.ProvidesResize etcom.google.gwt.user.client.ui.RequiresResize )

Exemples :

DockLayoutPanel

SplitLayoutPanel

TabLayoutPanel52

Page 53: TP GWT JDEV 2015

EXERCICE 3 : YET ANOTHER TODOLIST - UNE PREMIERE IHM

Page 54: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE PREMIÈRE IHM

Etape 1 : Suppression du contenu du contenur HTML

I Dans le fichier MonApplication.html vider le contenu de la balise<body> à l’exception de la balise <noscript> (et de son cotenu).

Etape 2 : Modification de la fonction onModuleLoad

I Modifier le fichier suivant MonApplication.java de la manièresuivante:public class MonApplication implements EntryPoint {

public void onModuleLoad() {DockLayoutPanel mainContent = new DockLayoutPanel(Unit.PX);mainContent.getElement().getStyle().setMargin(5, Unit.PX);mainContent.addNorth(new Label("Ma Todo List"), 25);VerticalPanel taskForm = new VerticalPanel();taskForm.setSpacing(5);taskForm.add(new Label("Ma tâche"));TextBox description = new TextBox();description.setTitle("Description");TextBox responsible = new TextBox();responsible.setTitle("Responsible");DateBox deadLine = new DateBox();taskForm.add(description);taskForm.add(responsible);taskForm.add(deadLine);mainContent.add(taskForm);RootLayoutPanel.get().add(mainContent);}}

54

Page 55: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE PREMIÈRE IHM

FinExercice3a

55

Page 56: TP GWT JDEV 2015

LIBRAIRIES COMPLÉMENTAIRES

Page 57: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LIBRAIRIES COMPLÉMENTAIRES

I Solutions spécifiques en GWT :

Sencha GXT (http://www.sencha.com/products/gxt/)Vaadin (https://vaadin.com/home)

Sencha GXT

57

Page 58: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LIBRAIRIES COMPLÉMENTAIRES

I Portage de libraries Javascript :

GWTBootstrap3 (https://github.com/gwtbootstrap3)Gwt-Openlayers (http://www.gwt-openlayers.org/)

Exemple GWTBootstrap3 :

Alert loginFirst = new Alert("You must connect to access to this page");

Remarque: un portage Javascript (Wrapping) peut occasionner un débogage plus difficile.58

Page 59: TP GWT JDEV 2015

EXERCICE 3 : YET ANOTHER TODOLIST - UNE IHM BOOTSTRAP

Page 60: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IHM BOOTSTRAP

Etape 1 : Ajout dépendance Maven

I Dans le fichier pom.xml ajouter les dépendances suivantes...<dependency><artifactId>gwtbootstrap3</artifactId><groupId>org.gwtbootstrap3</groupId><version>0.9</version></dependency>

<dependency><groupId>org.gwtbootstrap3</groupId><artifactId>gwtbootstrap3-extras</artifactId><version>0.9</version></dependency>...

Etape 2 : Modification du fichier MonApplication.gwt.xml

I Modifier le fichier suivant MonApplication.gwt.xml ajouter la lignesuivantes<inherits name="org.gwtbootstrap3.GwtBootstrap3"/>

Etape 3 : Redémarrage de l'application

I Une fois les modifications faites, redémarrer l’application.60

Page 61: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IHM BOOTSTRAP

Etape 4 : Modification de la fonction onModuleLoad

I Modifier le fichier suivant MonApplication.java de la manièresuivante:package fr.jdev.atelier.client;

import org.gwtbootstrap3.client.ui.Container;

import org.gwtbootstrap3.client.ui.Heading;

import org.gwtbootstrap3.client.ui.Jumbotron;

import org.gwtbootstrap3.client.ui.TextBox;

import org.gwtbootstrap3.client.ui.constants.HeadingSize;

...

public class MonApplication implements EntryPoint {

public void onModuleLoad() {

Jumbotron jumbotron = new Jumbotron();

Container container = new Container();

Heading heading = new Heading(HeadingSize.H1);

heading.setText("Ma Todo List");

container.add(heading);

jumbotron.add(container);

VerticalPanel mainContent = new VerticalPanel();

mainContent.setWidth("100%");

VerticalPanel taskForm = new VerticalPanel();

taskForm.setSpacing(5);

taskForm.add(new Label("Ma tâche"));

TextBox description = new TextBox();

description.setPlaceholder("Description");

TextBox responsible = new TextBox();

responsible.setPlaceholder("Responsible");

DateBox deadLine = new DateBox();

taskForm.add(description);

taskForm.add(responsible);

taskForm.add(deadLine);

mainContent.add(jumbotron);

mainContent.add(taskForm);

RootPanel.get().add(mainContent);

}

}

61

Page 62: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IHM BOOTSTRAP

FinExercice3b

62

Page 63: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CRÉATION DE COMPOSANTS

I Par héritage d’un Widget :Exemple: création d’une infobulle d’aide Classe :

Utilisation :HelpTooltip aide = new HelpTooltip("mon texte d’aide");monPanneau.add(aide);

Résultat :

63

Page 64: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CRÉATION DE COMPOSANTS

I Par héritage d’un Composite :Objectif: Permet de créer un composant en combinantplusieurs Widgets sans en exposer les méthodes.

Attention : il est nécessaire d’appeler la fonction initWidget surun des composants lors du constructeur.

64

Page 65: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CRÉATION DE COMPOSANTS

I Par implémentation de l’interface IsWidget :Le Widget est retourné par la méthode asWidget().

65

Page 66: TP GWT JDEV 2015

EXERCICE 3 : YET ANOTHER TODOLIST - CRÉATION DE COMPOSANTS

Page 67: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CRÉATION DE COMPOSANTS

Etape 1 : Création du composant HelpTooltip

I Créer la classe HelpTooltip suivante :public class HelpTooltip extends Popover {@UiConstructorpublic HelpTooltip(String text) {super();Icon helpIcon = new Icon(IconType.QUESTION_CIRCLE);helpIcon.setSize(IconSize.LARGE);add(helpIcon);setTitle("");setContent(text);}

public HelpTooltip(String text, Placement placement) {this(text);setPlacement(placement);}

public void setText(String text) {setContent(text);}}

67

Page 68: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IHM BOOTSTRAP

Etape 2 : Création du composant TaskCreationPanel

I Créer la classe TaskCreationPanel suivante :public class TaskCreationPanel implements IsWidget {

private VerticalPanel mainContainer;private TextBox description;private TextBox responsible;private DateBox deadLine;

public TaskCreationPanel() {mainContainer = new VerticalPanel();mainContainer.setSpacing(5);mainContainer.add(new Label("Ma tâche"));description = new TextBox();HorizontalPanel descriptionPanel = new HorizontalPanel();descriptionPanel.add(description);descriptionPanel.add(new HelpTooltip("Indiquez ici la description"));description.setPlaceholder("Description");responsible = new TextBox();responsible.setPlaceholder("Responsible");deadLine = new DateBox();mainContainer.add(descriptionPanel);mainContainer.add(responsible);mainContainer.add(deadLine);}

@Overridepublic Widget asWidget() {return mainContainer;}

}

68

Page 69: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UNE IHM BOOTSTRAP

Etape 3 : Modificiation de MonApplication

I Modifier la classe MonApplication de la manière suivante :...public void onModuleLoad() {Jumbotron jumbotron = new Jumbotron();Container container = new Container();Heading heading = new Heading(HeadingSize.H1);heading.setText("Ma Todo List");container.add(heading);jumbotron.add(container);VerticalPanel mainContent = new VerticalPanel();mainContent.setWidth("100%");mainContent.add(jumbotron);TaskCreationPanel taskCreationPanel = new TaskCreationPanel();mainContent.add(taskCreationPanel);RootPanel.get().add(mainContent);}...

FinExercice3c

69

Page 70: TP GWT JDEV 2015

UIBINDER

Page 71: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UIBINDER : MOTEUR DE TEMPLATES

I RôleSimplifier la création d’écran complexes avec un moteur detemplates

I PrincipeUn fichier de description, monFichier.ui.xml, permet de définirl’écran de manière similaire à une page HTML/JSP...Dans ce fichier les noms des balises importantes sont indiquésvia l’attribut ui:fieldUne classe, monFichier.java permet de définir le comportementdynamique associé à cet écran.Cette classe étend CompositeDans cette classe on retrouve le nom des attributs ui:fieldindiqués dans le fichier de description

71

Page 72: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UIBINDER : EXEMPLE

I Descripteur : MetadataSearchViewImpl.ui.xml

72

Page 73: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UIBINDER : EXEMPLE

I Classe : MetadataSearchViewImpl.java

73

Page 74: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UIBINDER : COMPLÉMENTS

I Instantication des champs ui:fieldSoit par le fichier de description lors de l’appel à initWidgetdans le constructeur :

initWidget(uiBinder.createAndBindUi(this));Soit manuellement

• En modifiant l’annotation UiField : @UiField(provided = true)• En instanciant les champs avant l’appel à initWidget .

I Ajout de comportement sur les éléments

Via l’annotation @UiHandlerLa signature de la méthode permet d’indiquer l’évènement géré

@UiHandler("searchButton")void onSearchButtonClicked(ClickEvent event){...}

74

Page 75: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UIBINDER : COMPLÉMENTS

I Utilisation de Widgets personnelsLa balise <ui:UiBinder> permet de définir via des espaces denommage les packages utilisables dans la page:<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"xmlns:l="urn:import:fr.sedoo.metadata.client.ui.widget.date">...<l:Iso19115DateBox ui:field="startDate" />

Des paramètres peuvent être transmis dans les attributs.Si le Widget possède plusieurs constructeurs, l’annotation@UiConstructeur permet d’indiquer celui que UiBinder va utiliser.

75

Page 76: TP GWT JDEV 2015

EXERCICE 3 : YET ANOTHER TODOLIST - UTILISATION UIBINDER

Page 77: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

Etape 1 : Ajouter la classe Task

Dans le package shared ajouter la classe suivante :

public class Task implements IsSerializable {

private String description;private String responsible;private Date deadLine;

public String getDescription() {return description;}

public void setDescription(String description) {this.description = description;}

public String getResponsible() {return responsible;}

public void setResponsible(String responsible) {this.responsible = responsible;}

public Date getDeadLine() {return deadLine;}

public void setDeadLine(Date deadLine) {this.deadLine = deadLine;}

}

77

Page 78: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

Etape 2 : Ajouter la classe NewTaskCreationPanel

Dans le package client ajouter la classe suivante :public class NewTaskCreationPanel extends Composite {

@UiFieldTextBox description;

@UiFieldTextBox responsible;

@UiFieldDateTimePicker deadLine;

private static LocalUiBinder uiBinder = GWT.create(LocalUiBinder.class);

interface LocalUiBinder extends UiBinder<Widget, NewTaskCreationPanel> {}

public NewTaskCreationPanel() {super();initWidget(uiBinder.createAndBindUi(this));}

public void reset() {description.setText("");responsible.setText("");deadLine.setValue(null);}

public Task flush() {Task result = new Task();result.setResponsible(responsible.getText());result.setDescription(description.getText());result.setDeadLine(deadLine.getValue());return result;}

}

78

Page 79: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

Etape 3 : Ajouter le fichier NewTaskCreationPanel.ui.xml

Dans le package client ajouter le fichier NewTaskCreationPanel.ui.xmlavec le contenu suivant :<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"><ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"xmlns:g="urn:import:com.google.gwt.user.client.ui"xmlns:b="urn:import:org.gwtbootstrap3.client.ui"xmlns:b2="urn:import:org.gwtbootstrap3.extras.datetimepicker.client.ui"><g:HTMLPanel width="90%"><h2>Enter a new task</h2><form class="form-horizontal" ><div class="form-group">

<label for="inputEmail3" class="col-sm-2 control-label">Description</label><div class="col-sm-10"><b:TextBox placeholder="Enter description" ui:field="description" />

</div></div><div class="form-group"><label for="inputEmail3" class="col-sm-2 control-label">Responsible</label><div class="col-sm-10"><b:TextBox placeholder="Enter responsible" ui:field="responsible"/>

</div></div><div class="form-group"><label for="inputEmail3" class="col-sm-2 control-label">Dead line</label><div class="col-sm-10"><b2:DateTimePicker ui:field="deadLine"/>

</div></div>

</form>

</g:HTMLPanel></ui:UiBinder>

79

Page 80: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

Etape 4 : Modification du fichier MonApplication.gwt.xml

I Dans le fichier MonApplication.gwt.xml ajouter la ligne suivantes<inherits name="org.gwtbootstrap3.extras.datetimepicker.DateTimePicker"/>

Etape 5 : Modification de la fonction onModuleLoad

I Dans le fichier MonApplication.java modifier la fonctiononModuleLoadpublic void onModuleLoad() {Jumbotron jumbotron = new Jumbotron();Container container = new Container();Heading heading = new Heading(HeadingSize.H1);heading.setText("Ma Todo List");container.add(heading);jumbotron.add(container);VerticalPanel mainContent = new VerticalPanel();mainContent.setWidth("100%");mainContent.add(jumbotron);NewTaskCreationPanel taskCreationPanel = new NewTaskCreationPanel();mainContent.add(taskCreationPanel);RootPanel.get().add(mainContent);}

80

Page 81: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

FinExercice3d

81

Page 82: TP GWT JDEV 2015

CLIENTFACTORY

Page 83: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CLIENTFACTORY

I Objectif : Optimiser le temps d’instanciation des objetscomplexes

I Problème : Certains composants clients sont coûteux àinstancier notamment les différents éléments de l’interfacegraphique.

I Solution : Utiliser une Factory ayant la charge d’instancier demanière unique - et si nécessaire - ces différents composants etde les transmettre aux objets voulant les utiliser (Exemple: lePresenter dans le modèle MVP) .

Remarque

Par ce mécanisme, les écrans graphiques ne sont créés qu’une seule fois. Ils sont par contre

remis à zéro (exemple : vidage des champs de saisie) lors de chaque utilisation.

Ce concept de Singleton est aussi étendu pour gérer les autresinstances uniques de l’application comme par exemple le busd’évènements (cf. infra). 83

Page 84: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE

I La mise en place de la ClientFactory et Activity est effectuée dela manière suivante:

1. Création de l’interface (ClientFactory ) et d’une ou plusieurs de sesimplémentations (ex ClientFactoryImpl,ClientFactoryMobileImpl...) dans le package client.

2. Déclaration dans le descripteur de module<replace-withclass="fr.jdev.atelier.client.ClientFactoryImpl"><when-type-is class="fr.jdev.atelier.client.ClientFactory" /></replace-with>

Dans cet exemple la classe, au moment de la compilation Javavers Javascript, ClientFactory sera remplacée parClientFactoryImpl lorsqu’elle est appellée via GWT.create(). Onpeut imaginer des statégies plus fines (en fonction dupériphérique client, ...)

3. Instanciation du singleton, normalement dans le onModuleLoad.clientFactory = GWT.create(ClientFactory.class);

84

Page 85: TP GWT JDEV 2015

BUS D'ÉVÈNEMENTS

Page 86: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

BUS D'ÉVÈNEMENTS

I Objectif : Simplifier la communication entre les composantsI Problème : Les interfaces des applications GWT peuvent

contenir de nombreux composants qui doivent dialoguer entreeux. Toutefois, dans certains cas ce dialogue ne peux pas sefaire directement

Pour éviter un trop fort couplage entre les classes.Parce que les composants cibles du dialogue ne peuvent pas êtreconnus du composant source.

I Solution : GWT propose un bus permettant l’échanged’évènements entre composants reposant sur un mécanismed’abonnement:

1. Un type d’évènement spécifique est défini.2. Les composants cibles s’abonnent à ce type d’évènement auprès

du bus.3. Lorsque nécessaire, le composant source instancie un évènement

et demande sa propagation sur le bus.86

Page 87: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DÉFINITION D'UN ÉVÈNEMENT

I Exemple : évènement signalant la connexion d’un utilisateur -UserLoginEventIl est nécessaire de créer deux classes:

Le gestionnaire : UserLoginEventHandlerL’évènement : UserLoginEvent

I Le gestionnaire

Interface qui sera implémentée par les classes écoutantl’évènementDoit étendre com.google.gwt.event.shared.EventHandler

87

Page 88: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DÉFINITION D'UN ÉVÈNEMENT

I L’évènement

La classe doit étendrecom.google.gwt.event.shared.GwtEventElle définit un attribut statique - traditionnellement nommé TYPE -qui va identifier l’évènement et permettre de s’y abonner auprèsdu bus.

88

Page 89: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ABONNEMENT ET PUBLICATION

I Abonnement à un évènementL’abonnement auprès du bus s’effectue via la méthodeaddHandler en passant en paramètres le type de l’évènement etle composant cible.Celui-ci doit implémenter le Handler correspondant àl’évènement :

EVENT_BUS.addHandler(UserLoginEvent.TYPE, monComposantCible);

I Publication d’un évènement La diffusion d’un évènement sur le bus s’effectue de lamanière suivante :

UserLoginEvent monEvenement = new UserLoginEvent();// Valorisation de l’objet monEvenement ...EVENT_BUS.fireEvent(monEvenement);

89

Page 90: TP GWT JDEV 2015

EXERCICE 4 : AJOUT D'UNÉVÈNEMENT

Page 91: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AJOUT D'UN ÉVÈNEMENT

Etape 1 : Ajouter la classe NotificationEvent

Dans le package client.event ajouter la classe suivante :

public class NotificationEvent extends GwtEvent<NotificationEventHandler> {

public static final Type<NotificationEventHandler> TYPE = new Type<NotificationEventHandler>();

private String message;

public NotificationEvent(String message) {this.setMessage(message);}

@Overrideprotected void dispatch(NotificationEventHandler handler) {handler.onNotification(this);}

@Overridepublic com.google.gwt.event.shared.GwtEvent.Type<NotificationEventHandler> getAssociatedType() {return TYPE;}

public String getMessage() {return message;}

public void setMessage(String message) {this.message = message;}

}

91

Page 92: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AJOUT D'UN ÉVÈNEMENT

Etape 2 : Ajouter l'interface NotificationEventHandler

Dans le package client.event ajouter l’interface suivante :

public interface NotificationEventHandler extends EventHandler {void onNotification(NotificationEvent event);}

Etape 3 : Ajouter l'interface ClientFactory

Dans le package client ajouter l’interface suivante :

public interface ClientFactory extends NotificationEventHandler {EventBus getEventBus();

}

92

Page 93: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AJOUT D'UN ÉVÈNEMENT

Etape 4 : Ajouter la classe ClientFactoryImpl

Dans le package client ajouter la classe suivante :

public class ClientFactoryImpl implements ClientFactory {

private static final EventBus EVENT_BUS = new SimpleEventBus();

public ClientFactoryImpl() {getEventBus().addHandler(NotificationEvent.TYPE, this);}

@Overridepublic EventBus getEventBus() {return EVENT_BUS;}

@Overridepublic void onNotification(NotificationEvent event) {Growl.growl(event.getMessage());}

93

Page 94: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AJOUT D'UN ÉVÈNEMENT

Etape 5 : Modification du fichier MonApplication.gwt.xml

Modifier le fichier MonApplication.gwt.xml en ajoutant les lignes :

<inherits name="org.gwtbootstrap3.extras.growl.Growl"/>

<replace-withclass="fr.jdev.atelier.client.ClientFactoryImpl"><when-type-is class="fr.jdev.atelier.client.ClientFactory" /></replace-with>

94

Page 95: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

AJOUT D'UN ÉVÈNEMENT

Etape 6 : Modification du fichier MonApplication.java

Modifier le fichier MonApplication.java de la manière suivante :

public class MonApplication implements EntryPoint {

private static ClientFactory clientFactory;

public static ClientFactory getClientFactory() {

if (clientFactory == null) {

clientFactory = GWT.create(ClientFactory.class);

}

return clientFactory;

}

public void onModuleLoad() {

clientFactory = getClientFactory();

Jumbotron jumbotron = new Jumbotron();

Container container = new Container();

Heading heading = new Heading(HeadingSize.H1);

heading.setText("Ma Todo List");

container.add(heading);

jumbotron.add(container);

VerticalPanel mainContent = new VerticalPanel();

mainContent.getElement().getStyle().setMargin(5, Unit.PX);

mainContent.getElement().getStyle().setBorderColor("white");

mainContent.getElement().getStyle().setBorderWidth(2, Unit.PCT);

mainContent.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);

mainContent.add(jumbotron);

NewTaskCreationPanel taskCreationPanel = new NewTaskCreationPanel();

mainContent.add(taskCreationPanel);

Button addButton = new Button("Add");

addButton.setIcon(IconType.PLUS);

addButton.setType(ButtonType.PRIMARY);

addButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

getClientFactory().getEventBus().fireEvent(new NotificationEvent("Task added..."));

}

});

mainContent.add(addButton);

mainContent.setWidth("98%");

RootPanel.get().add(mainContent);

}

}

95

Page 96: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION UIBINDER

FinExercice4

96

Page 97: TP GWT JDEV 2015

CINÉMATIQUE DE L'APPLICATION

Page 98: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

TROIS COMPOSANTS STRUCTURANTS

I La cinématique d’une application Ajax diffère d’une applicationWeb traditionnelle où le serveur joue un rôle de chef d’orchestre.

I Les versions récentes de GWT ont introduit un certain nombre debonnes pratiques permettant la construction rigoureuse d’unetelle cinématique:

Gestion de l’historiqueActivities and PlacesPatron Model-View-Presenter

98

Page 99: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GESTION DE L'HISTORIQUE

I Objectif : Permettre une gestion complète de l’historique,notamment la navigation via les boutons Précédent /Suivant

I Principe :Chaque état de l’application est sérialisé sous forme d’une chaine(token) ajoutée à l’URL actuelle sous forme d’un lien nommé(c.a.d séparé par un #). Exemple :http://sedoo.sedoo.fr/portailresif/#WelcomePlace:

Un évènement de type navigation (Précédent, Suivant,Rafraichissement) déclenche un évènement de typeValueChangeEvent .

99

Page 100: TP GWT JDEV 2015

GESTION DE L'HISTORIQUE

Page 101: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GESTION DE L'HISTORIQUE

I Mise en œuvre :Activation dans le conteneur HTML<iframe src="javascript:’’" id="__gwt_historyFrame"style="position:absolute;width:0;height:0;border:0"></iframe>

Une nouvelle étape dans l’historique est ajoutée en appelantHistory.newItem(token)Chaque objet voulant réagir aux évènement de l’historique s’abonne auxHistory.addValueChangeHandler() . Chaque abonné devra déterminer

• si l’évènement le concerne• comment reconstruire l’état correspondant au token.

101

Page 102: TP GWT JDEV 2015

ACTIVITIES AND PLACES

Page 103: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ACTIVITIES

I Activity : Une activité est une fonctionnalité de l’applicationeffectuée par un utilisateur.Exemples : LoginActivity , SearchActivity ...Une activité étendcom.google.gwt.activity.shared.AbstractActivity

I Cycle de vie : La gestionnaire d’activité(com.google.gwt.activity.shared.ActivityManager)active et désactive les activités via les méthodes suivantes :

startInvoquée lors du démarage de l’activité. A son is-sue, l’activité doit fournir la vue lui correspondant.

mayStopInvoquée pour savoir si l’activité en cours peut s’ar-rêter.

onStop Invoquée lors de l’arrêt de l’activité.

onCancelInvoquée lorsque le démarrage n’est pas termn-iné mais que l’utilisateur a demandé le début d’uneautre activité.

103

Page 104: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PLACES

I Place : Une place représente un état d’utilisation d’une activité. Ildoit pouvoir être sérialisé sous forme de token conformément aumécanisme de gestion de l’historique.

I Mise en œuvre :

Une place hérite de com.google.gwt.place.shared.Place .Le tokenizer associé à la place hérite decom.google.gwt.place.shared.PlaceTokenizer .Il permet la sérialisation/désérialisation de l’état via les méthodessuivantes :getPlace Construit la place à partir du token.getToken Sérialise la place sous forme de token.

Bonne pratique

A chaque instanciation d’une activité, une place va lui être transmise afin que l’activité recrée

son état.

104

Page 105: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

NAVIGATION VIA LES PLACES

I Les places sont le meilleur moyen de naviguer au sein d’uneapplication GWT.Le mécanisme est le suivant:

1. Instanciation et valoriastion de la place souhaitée2. Récupération de l’instance du PlaceController (Cf.

ClientFactory )3. Appel de la méthode PlaceController.goTo(place)4. Si la place souhaitée n’est pas la place en cours, l’activité

correspondante à la place est instanciée (cf. page suivante).5. La méthode start de l’activité est appelée.

Remarques

Ce mécanisme est également celui utilisé lors de l’analyse d’une URL pointant sur uneplace de l’application.

Le PlaceController utilise la méthode equals pour comparer place actuelle et

destination. Le cas échéant il peut être nécessaire de surcharger cette méthode

105

Page 106: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

NAVIGATION VIA LES PLACES

I La correspondance entre Place et Activity est effectuée de lamanière suivante:

1. Le PlaceController envoie un évènement de changement deplace (PlaceChangeEvent)

2. L’évènement est reçu par le gestionnaire d’activités(ActivityManager)

3. Le gestionnaire d’activités utilise son ActivityMapper qui luiindique l’activité à démarrer via la méthodeActivity getActivity(Place place);

La classe ActivityMapper est donc le composant central dumécanisme.Exemplepublic Activity getActivity(Place place) {if (place instanceof WelcomePlace){return new WelcomeActivity((WelcomePlace) place, clientFactory);}...}

106

Page 107: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

NAVIGATION VIA LES PLACES

Activité A ActivityManager ActivityMapper Activité B PlaceController EventBus ClientFactory

évènement

crééPlaceB()

getPlaceController()

goTo(placeB)()

fireEvent(placeChangeRequestEvent(placeB))

onPlaceChangeRequest(PlaceChangeRequestEvent)(placeB)

mayStop()

fireEvent(placeChangeEvent(placeB))

onPlaceChange(placeB)

getActivity(placeB)

nouvelle activité BonStop()

start()

107

Page 108: TP GWT JDEV 2015

PATRON MODEL-VIEW-PRESENTER

Page 109: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

PATRON MODEL-VIEW-PRESENTER

GWT étend le traditionnel modèle MVC avec le patron MVP danslequel le Presenter tient le rôle central.

Nom Situation RôleModel Côté serveur Récupère les données (via les DAO).

View Côté clientAffichage des données transmises par le Presenter.

Transmet au Presenter les évènements importants

(exemple: click sur des boutons,...)

Presenter Côté clientMobilise le Model et transmet les données à la vue.

Réagit aux évènements transmis par la vue afin nota-

ment de dialoguer avec le Model ou changer de Place

Stratégie

I L’objectif est de postionner un maximum d’intelligence au niveau du Presenter afinque celui-ci puisse fonctionner indifféremment avec plusieurs implémentations de View(exemple: View pour un écran d’ordinateur de grande taille, View pour un mobile, Viewficitve pour les tests...).

I La View est donc dépourvue de traitements outre ceux spécifiques à sonimplémentation. Ceci permet de l’exclure plus ou moins de la chaine de test.

109

Page 110: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

DIAGRAMME MVP

Presenter

ModelView

110

Page 111: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

INTÉGRATION AVEC LE MODÈLE ACTIVITIES AND PLACES

L’activity joue le rôle du Presenter

111

Page 112: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE D'UNE VIEW

I Une View doit être définie sous forme d’une Interface qui étendcom.google.gwt.user.client.ui.IsWidget.

I Le Presenter ne doit connaître que cette Interface.I Si la View doit pouvoir transmettre des informations au

Presenter, l’usage veut que celui-ci soit défini comme unesous-interface de la View. Dans ce cas:

La View doit définir une methode setPresenter correspondante.L’Activity doit implémenter le Presenter.

112

Page 113: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

RÉCUPÉRATION DE LA VIEW PAR LE PRESENTER

I Le lien entre une View et l’implémentation à utiliser dans lecontexte courant est fait par la ClientFactory.Ceci permet d’envisager la mise en place de plusieursimplémentations de ClientFactory :

pour les mobilespour les tests...

113

Page 114: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CINÉMATIQUE D'UTILISATION

Classiquement, la cinématique d’utilisation est la suivante:

1. L’Activity récupère l’instance de la View auprès de laClientFactory (dans sa méthode start)

2. Si nécessaire, utilise la méthode setPresenter de la View pourpermettre une communication View ⇒ Presenter.

3. L’Activity remet à zéro l’instance de la View (qui a peut être serviau préalable)

4. L’Activity recherche auprès du Model les informationsnécessaires

5. L’Activity les transmet à la vue qui les positionne.

6. L’Activity affiche la vue via la commande

containerWidget.setWidget(view.asWidget());

114

Page 115: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CINÉMATIQUE D'UTILISATION

ActivityManager MonActivité MaVue MonModèle ClientFactory

start()

getMaVue()

instance de MaVuesetPresenter(this)

reset()

chargeInformations()

afficheInformations()

affiche la vue

115

Page 116: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

COMMUNICATION PRESENTER - MODEL

La communication entre le Presenter et le Model s’effectue via lemécanisme GWT-RPC décrit dans la section suivante.

116

Page 117: TP GWT JDEV 2015

EXERCICE 5 : MISE EN PLACE MVP

Page 118: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 1 : Modification du fichier MonApplication.gwt.xml

Dans le fichier MonApplication.gwt.xml ajouter les lignes suivantes :

<inherits name="com.google.gwt.activity.Activity" /><inherits name="com.google.gwt.place.Place" />

Etape 2 : Modification du fichier Task.java

Dans le fichier Task.java ajouter les lignes suivantes :

private String uuid;

public String getUuid() {return uuid;}

public void setUuid(String uuid) {this.uuid = uuid;}

118

Page 119: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 3 : Modification du fichier ClientFactory.java

Dans le fichier ClientFactory.java ajouter les lignes suivantes :

PlaceController getPlaceController();

WelcomeView getWelcomeView();

TaskConsultView getTaskConsultView();

TaskListView getTaskListView();

119

Page 120: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 4 : Modification du fichier ClientFactoryImpl.java

Modifier le fichier ClientFactoryImpl.java de la manière suivante :

public class ClientFactoryImpl implements ClientFactory {

private static final EventBus EVENT_BUS = new SimpleEventBus();

private static final PlaceController PLACE_CONTROLLER = new PlaceController(EVENT_BUS);

WelcomeView welcomeView = new WelcomeViewImpl();

TaskListView taskListView = new TaskListViewImpl();

public ClientFactoryImpl() {

getEventBus().addHandler(NotificationEvent.TYPE, this);

}

@Override

public EventBus getEventBus() {

return EVENT_BUS;

}

@Override

public void onNotification(NotificationEvent event) {

Growl.growl(event.getMessage());

}

@Override

public PlaceController getPlaceController() {

return PLACE_CONTROLLER;

}

@Override

public WelcomeView getWelcomeView() {

return welcomeView;

}

@Override

public TaskConsultView getTaskConsultView() {

return null;

}

@Override

public TaskListView getTaskListView() {

return taskListView;

}

}

120

Page 121: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 5 : Création de la classeWelcomePlace.java

Dans le package client.place ajouter la classe suivante :

public class WelcomePlace extends Place {

public static class Tokenizer implements PlaceTokenizer<WelcomePlace> {public WelcomePlace getPlace(String token) {

return new WelcomePlace();}

public String getToken(WelcomePlace place) {return "";}}}

121

Page 122: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 6 : Création de la classe TaskListPlace.java

Dans le package client.place ajouter la classe suivante :

public class TaskListPlace extends Place {

public TaskListPlace() {}

public static class Tokenizer implements PlaceTokenizer<TaskListPlace> {public TaskListPlace getPlace(String token) {return new TaskListPlace();}

public String getToken(TaskListPlace place) {return "";}}}

122

Page 123: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 7 : Création de la classe TaskConsultPlace.java

Dans le package client.place ajouter la classe suivante :

public class TaskConsultPlace extends Place {

private String taskUuid;

public TaskConsultPlace() {}

public String getTaskUuid() {return taskUuid;}

public void setTaskUuid(String taskUuid) {this.taskUuid = taskUuid;}

public static class Tokenizer implements PlaceTokenizer<TaskConsultPlace> {public TaskConsultPlace getPlace(String token) {TaskConsultPlace place = new TaskConsultPlace();place.setTaskUuid(token);return place;}

public String getToken(TaskConsultPlace place) {return "";}}}

123

Page 124: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 8 : Création de la classe AppActivityMapper.java

Dans le package client.mvp ajouter la classe suivante :

public class AppActivityMapper implements ActivityMapper {

private ClientFactory clientFactory;

public AppActivityMapper(ClientFactory clientFactory) {super();this.clientFactory = clientFactory;}

@Overridepublic Activity getActivity(Place place) {if (place instanceof TaskConsultPlace) {return new TaskConsultActivity((TaskConsultPlace) place, clientFactory);} else if (place instanceof TaskListPlace) {return new TaskListActivity((TaskListPlace) place, clientFactory);} else {return new WelcomeActivity(new WelcomePlace(), clientFactory);}}}

124

Page 125: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 9 : Création de la classe AppPlaceHistoryMapper.java

Dans le package client.mvp ajouter la classe suivante :

@WithTokenizers({ WelcomePlace.Tokenizer.class, TaskConsultPlace.Tokenizer.class, TaskListPlace.Tokenizer.class })public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {}

125

Page 126: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 10 : Création de la classeWelcomeActivity.java

Dans le package client.activity ajouter la classe suivante :

public class WelcomeActivity extends AbstractActivity implements Presenter {

private ClientFactory clientFactory;private WelcomeView welcomeView;

public WelcomeActivity(WelcomePlace place, ClientFactory clientFactory) {this.clientFactory = clientFactory;}

@Overridepublic void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {welcomeView = clientFactory.getWelcomeView();welcomeView.setPresenter(this);welcomeView.reset();containerWidget.setWidget(welcomeView.asWidget());

}

@Overridepublic void addTask(Task task) {Window.alert("A coder dans le prochain exercice");}

@Overridepublic void showList() {clientFactory.getPlaceController().goTo(new TaskListPlace());

}}

126

Page 127: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 11 : Création de la classe TaskListActivity.java

Dans le package client.activity ajouter la classe suivante :

public class TaskListActivity extends AbstractActivity implements Presenter {

private ClientFactory clientFactory;private TaskListView taskListView;

public TaskListActivity(TaskListPlace place, ClientFactory clientFactory) {this.clientFactory = clientFactory;}

@Overridepublic void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {taskListView = clientFactory.getTaskListView();taskListView.reset();containerWidget.setWidget(taskListView.asWidget());

}

@Overridepublic void display(String taskUuid) {TaskConsultPlace taskConsultPlace = new TaskConsultPlace();taskConsultPlace.setTaskUuid(taskUuid);clientFactory.getPlaceController().goTo(taskConsultPlace);

}

}

127

Page 128: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 12 : Création de la classe TaskConsultActivity.java

Dans le package client.activity ajouter la classe suivante :

public class TaskConsultActivity extends AbstractActivity {

private ClientFactory clientFactory;private TaskConsultView taskConsultView;private String taskUuid;

public TaskConsultActivity(TaskConsultPlace place, ClientFactory clientFactory) {this.clientFactory = clientFactory;taskUuid = place.getTaskUuid();}

@Overridepublic void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {taskConsultView = clientFactory.getTaskConsultView();taskConsultView.reset();containerWidget.setWidget(taskConsultView.asWidget());

}

}

128

Page 129: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 13 : Création de la classeWelcomeView.java

Dans le package client.view ajouter la classe suivante :

public interface WelcomeView extends IsWidget {

void reset();

void setRecentTask(ArrayList<Task> tasks);

void setPresenter(Presenter presenter);

public interface Presenter {void addTask(Task task);

void showList();}}

129

Page 130: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 14 : Création de la classe TaskListView.java

Dans le package client.view ajouter la classe suivante :

public interface TaskListView extends IsWidget {

void reset();

void displayTasks(ArrayList<Task> tasks);

void setPresenter(Presenter presenter);

public interface Presenter {void display(String taskUuid);}

}

130

Page 131: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 15 : Création de la classe TaskConsultView.java

Dans le package client.view ajouter la classe suivante :

public interface TaskConsultView extends IsWidget {

void reset();

void display(Task task);

}

131

Page 132: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 16 : Création de la classeWelcomeViewImpl.java

Dans le package client.view ajouter la classe suivante :

public class WelcomeViewImpl extends VerticalPanel implements WelcomeView {

private NewTaskCreationPanel taskCreationPanel;

private Presenter presenter;

public WelcomeViewImpl() {

super();

getElement().getStyle().setMargin(5, Unit.PX);

getElement().getStyle().setBorderColor("white");

getElement().getStyle().setBorderWidth(2, Unit.PCT);

getElement().getStyle().setBorderStyle(BorderStyle.SOLID);

taskCreationPanel = new NewTaskCreationPanel();

add(taskCreationPanel);

Button addButton = new Button("Add");

addButton.setIcon(IconType.PLUS);

addButton.setType(ButtonType.PRIMARY);

addButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

presenter.addTask(taskCreationPanel.flush());

}

});

add(addButton);

Button taskListButton = new Button("View all");

taskListButton.getElement().getStyle().setMarginTop(5, Unit.PX);

taskListButton.setIcon(IconType.LIST);

taskListButton.setType(ButtonType.PRIMARY);

taskListButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

presenter.showList();

}

});

add(taskListButton);

setWidth("98%");

}

@Override

public void reset() {

taskCreationPanel.reset();

}

@Override

public void setRecentTask(ArrayList<Task> tasks) {

}

@Override

public void setPresenter(Presenter presenter) {

this.presenter = presenter;

}

}

132

Page 133: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 17 : Création de la classe TaskListViewImpl.java

Dans le package client.view ajouter la classe suivante :

public class TaskListViewImpl extends VerticalPanel implements TaskListView {

private Presenter presenter;

public TaskListViewImpl() {super();

getElement().getStyle().setMargin(5, Unit.PX);getElement().getStyle().setBorderColor("white");getElement().getStyle().setBorderWidth(2, Unit.PCT);getElement().getStyle().setBorderStyle(BorderStyle.SOLID);

Heading title = new Heading(HeadingSize.H2);title.setText("Task List");

add(title);

}

@Overridepublic void reset() {

}

@Overridepublic void setPresenter(Presenter presenter) {this.presenter = presenter;}

@Overridepublic void displayTasks(ArrayList<Task> tasks) {

}

}

133

Page 134: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE MVP

Etape 18 : Modification de la classe MonApplication.java

Modifier la classe MonApplication.java de la manière suivante :

public class MonApplication implements EntryPoint {

private static ClientFactory clientFactory;

private ContentPanel dynamicPanel = new ContentPanel();

private Div staticContentPanel;

public static ClientFactory getClientFactory() {

if (clientFactory == null) {

clientFactory = GWT.create(ClientFactory.class);

}

return clientFactory;

}

public void onModuleLoad() {

clientFactory = getClientFactory();

initGui();

PlaceController placeController = getClientFactory().getPlaceController();

// Start ActivityManager for the main widget with our ActivityMapper

ActivityMapper activityMapper = new AppActivityMapper(getClientFactory());

ActivityManager activityManager = new ActivityManager(activityMapper, getClientFactory().getEventBus());

activityManager.setDisplay(dynamicPanel);

// Start PlaceHistoryHandler with our PlaceHistoryMapper

AppPlaceHistoryMapper historyMapper = GWT.create(AppPlaceHistoryMapper.class);

PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);

historyHandler.register(placeController, getClientFactory().getEventBus(), new WelcomePlace());

historyHandler.handleCurrentHistory();

}

private void initGui() {

staticContentPanel = new Div();

Jumbotron jumbotron = new Jumbotron();

Container container = new Container();

Heading heading = new Heading(HeadingSize.H1);

heading.setText("Ma Todo List");

container.add(heading);

jumbotron.add(container);

staticContentPanel.add(jumbotron);

staticContentPanel.add(dynamicPanel);

RootPanel.get().add(staticContentPanel);

}

private class ContentPanel extends VerticalPanel implements AcceptsOneWidget {

public ContentPanel() {

super();

setWidth("100%");

}

@Override

public void setWidget(IsWidget w) {

if (w != null) {

clear();

add(w.asWidget());

}

}

}

}

134

Page 135: TP GWT JDEV 2015

COMMUNICATION CLIENT-SERVEUR

Page 136: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GWT-RPC

GWT-RPC (Remote Procedure Call) est un mécanisme simple decommunication client/serveur.

La mise en place d’un service RPC - par exemple MonService - passepar la création de trois classes:

I Côté clientMonService : Définit l’interface du serviceMonServiceAsync : Équivalent asynchrone de l’interfaceMonService

I Côté serveurMonServiceImpl : Servlet implémentant le service (accès auxDAO...)

Rappel

Les objets pouvant transiter entre le serveur et le client doivent

I être situés dans le package shared

I être des beans sérialisables

136

Page 137: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

GWT-RPC

137

Page 138: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE CÔTÉ CLIENT

I Interface MonService

L’interface doit étendrecom.google.gwt.user.client.rpc.RemoteService.L’annotation @RemoteServiceRelativePath va permettred’associer la partie cliente à la servlet correspondante.

138

Page 139: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE CÔTÉ CLIENT

I Interface MonServiceAsyncCette classe reprend les méthodes de MonService en leurrajoutant un aspect asynchrone (via les AsyncCallback ).Elle peut être générée automatiquement à partir de MonService(Eclipse propose cette possibilité via le QuickFix Createasynchronous RemoteService ... )Elle permet une communication asynchrone afin de ne pasbloquer le navigateur. C’est uniquement cette classe qui serautilisée concrètement.

139

Page 140: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

MISE EN PLACE CÔTÉ SERVEUR

I Classe MonServiceImplElle étend com.google.gwt.user.server.rpc.RemoteServiceServlet.Elle implémente MonService .

I Fichier web.xmlLa classe MonServiceImpl est une servlet. Elle doit êtredéclarée et mappée correctement dans le fichier web.xml. Cemapping doit correspondre à la valeur indiquée pour l’annotation@RemoteServiceRelativePath

140

Page 141: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

UTILISATION DU SERVICE

Typiquement, un service RPC doit être utilisé par le Presenter.

I InstanciationElle utilise le mécanisme GWT.create afin de créer la classeMonServiceAsync :private final MonServiceAsync MON_SERVICE = GWT.create(MonService.class);

I UtilisationLes appels asynchrones nécessitent la mise en place - souvent anonyme - de classes deCallBack qui permettent de définir les traitements à effectuer en cas de réussite ou desuccès.

141

Page 142: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

ASPECT ASYNCHRONE DES ÉCHANGES

Les appels du client vers le serveur sont asynchrones. Il faut doncbien veiller à faire en sorte que les traitements dépendants du résultat(exemple : mise à jour de l’IHM) soient positionnés dans les fonctionsde callBack (onSuccess et onFailure) et non à la suite de l’appel.

142

Page 143: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

LIMITATIONS DE GWT-RPC

I RPC est un mécanisme assez simple qui contient certaineslimitations. La principale est l’utilisation d’interfaces de type Listou Set pour les types d’échanges.

I Celle-ci est totalement possible. Toutefois, lors de la compilationen Javascript, une traduction pour chaque implémentationconcrète présente dans l’émulation du JRE (ArrayList, Vector...)va être ajoutée, alourdissant ainsi le code généré.

I Ainsi, les types concrets doivent être privilégiés à ce niveau.

I Le mécanisme RequestFactory propose par rapport à RPC uncertain nombre d’améliorations permettant d’avoir des échangesplus optimisés entre le client et le serveur.

143

Page 144: TP GWT JDEV 2015

EXERCICE 6 : MISE EN PLACEGWT-RPC

Page 145: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 1 : Ajout/modification de la classe TaskListPanel.java

Ajouter/Modifier la classe suivante :

public class TaskListPanel extends VerticalPanel {

private DetailPresenter presenter;

public TaskListPanel() {

super();

setWidth("100%");

}

public void reset() {

clear();

}

public void setTasks(ArrayList<Task> tasks) {

reset();

int i = 0;

Grid grid = new Grid(tasks.size(), 4);

grid.setWidth("100%");

for (Task task : tasks) {

grid.setWidget(i, 0, new Label(task.getDescription()));

grid.setWidget(i, 1, new Label(task.getResponsible()));

grid.setWidget(i, 2, new Label(task.getDeadLine().toString()));

Button detailButton = new Button("Detail");

detailButton.setType(ButtonType.PRIMARY);

detailButton.setSize(ButtonSize.SMALL);

final String uuid = task.getUuid();

detailButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

TaskConsultPlace taskConsultPlace = new TaskConsultPlace();

taskConsultPlace.setTaskUuid(uuid);

MonApplication.getClientFactory().getPlaceController().goTo(taskConsultPlace);

}

});

grid.setWidget(i, 3, detailButton);

i++;

}

add(grid);

}

public void setPresenter(DetailPresenter presenter) {

this.presenter = presenter;

}

} 145

Page 146: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 2 : Ajout/modification de la classe TaskConsultActivity.java

Ajouter/Modifier la classe suivante dans le package client.activity :

public class TaskConsultActivity extends AbstractActivity {

private ClientFactory clientFactory;private TaskConsultView taskConsultView;private String taskUuid;private static final TaskServiceAsync TASK_SERVICE = GWT.create(TaskService.class);

public TaskConsultActivity(TaskConsultPlace place, ClientFactory clientFactory) {this.clientFactory = clientFactory;taskUuid = place.getTaskUuid();}

@Overridepublic void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {taskConsultView = clientFactory.getTaskConsultView();taskConsultView.reset();containerWidget.setWidget(taskConsultView.asWidget());TASK_SERVICE.findByUuid(taskUuid, new AsyncCallback<Task>() {

@Overridepublic void onSuccess(Task result) {taskConsultView.display(result);}

@Overridepublic void onFailure(Throwable caught) {Window.alert("KO");

}});}}

146

Page 147: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 3 : Ajout/modification de la classe TaskListActivity.java

Ajouter/Modifier la classe suivante dans le package client.activity :

public class TaskListActivity extends AbstractActivity implements Presenter {

private ClientFactory clientFactory;

private TaskListView taskListView;

private static final TaskServiceAsync TASK_SERVICE = GWT.create(TaskService.class);

public TaskListActivity(TaskListPlace place, ClientFactory clientFactory) {

this.clientFactory = clientFactory;

}

@Override

public void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {

taskListView = clientFactory.getTaskListView();

taskListView.setPresenter(this);

taskListView.reset();

containerWidget.setWidget(taskListView.asWidget());

findAll();

}

private void findAll() {

TASK_SERVICE.findAll(new AsyncCallback<ArrayList<Task>>() {

@Override

public void onSuccess(ArrayList<Task> result) {

taskListView.displayTasks(result);

}

@Override

public void onFailure(Throwable caught) {

Window.alert("KO");

}

});

}

@Override

public void display(String taskUuid) {

TaskConsultPlace taskConsultPlace = new TaskConsultPlace();

taskConsultPlace.setTaskUuid(taskUuid);

clientFactory.getPlaceController().goTo(taskConsultPlace);

}

}

147

Page 148: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 4 : Ajout/modification de la classeWelcomeActivity.java

Ajouter/Modifier la classe suivante dans le package client.activity :

public class WelcomeActivity extends AbstractActivity implements Presenter {

private ClientFactory clientFactory;

private WelcomeView welcomeView;

private static final TaskServiceAsync TASK_SERVICE = GWT.create(TaskService.class);

public WelcomeActivity(WelcomePlace place, ClientFactory clientFactory) {

this.clientFactory = clientFactory;

}

@Override

public void start(AcceptsOneWidget containerWidget, final EventBus eventBus) {

welcomeView = clientFactory.getWelcomeView();

welcomeView.setPresenter(this);

welcomeView.reset();

containerWidget.setWidget(welcomeView.asWidget());

findLatest();

}

private void findLatest() {

TASK_SERVICE.findLatest(new AsyncCallback<ArrayList<Task>>() {

@Override

public void onSuccess(ArrayList<Task> result) {

welcomeView.setRecentTask(result);

}

@Override

public void onFailure(Throwable caught) {

Window.alert("KO");

}

});

}

@Override

public void addTask(Task task) {

TASK_SERVICE.save(task, new AsyncCallback<Task>() {

@Override

public void onSuccess(Task result) {

clientFactory.getEventBus().fireEvent(new NotificationEvent("Saved"));

findLatest();

}

@Override

public void onFailure(Throwable caught) {

Window.alert("KO");

}

});

}

@Override

public void showList() {

clientFactory.getPlaceController().goTo(new TaskListPlace());

}

@Override

public void display(String taskUuid) {

TaskConsultPlace taskConsultPlace = new TaskConsultPlace();

taskConsultPlace.setTaskUuid(taskUuid);

clientFactory.getPlaceController().goTo(taskConsultPlace);

}

}

148

Page 149: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 5 : Ajout/modification de la classe TaskConsultPlace.java

Ajouter/Modifier la classe suivante dans le package client.place:

public class TaskConsultPlace extends Place {

private String taskUuid;

public TaskConsultPlace() {}

public String getTaskUuid() {return taskUuid;}

public void setTaskUuid(String taskUuid) {this.taskUuid = taskUuid;}

public static class Tokenizer implements PlaceTokenizer<TaskConsultPlace> {public TaskConsultPlace getPlace(String token) {TaskConsultPlace place = new TaskConsultPlace();place.setTaskUuid(token);return place;}

public String getToken(TaskConsultPlace place) {return place.getTaskUuid();}}}

149

Page 150: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 6 : Ajout/modification de la classe TaskService.java

Ajouter/Modifier la classe suivante dans le package client.service:

@RemoteServiceRelativePath("tasks")public interface TaskService extends RemoteService {

Task save(Task task);

ArrayList<Task> findLatest();

ArrayList<Task> findAll();

Task findByUuid(String uuid);

}

150

Page 151: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 7 : Ajout/modification de la classe TaskServiceAsync.java

Ajouter/Modifier la classe suivante dans le package client.service:

public interface TaskServiceAsync {

void findAll(AsyncCallback<ArrayList<Task>> callback);

void findLatest(AsyncCallback<ArrayList<Task>> callback);

void save(Task task, AsyncCallback<Task> callback);

void findByUuid(String uuid, AsyncCallback<Task> callback);

}

Etape 8 : Ajout/modification de la classe DetailPresenter.java

Ajouter/Modifier la classe suivante dans le package client.view :

public interface DetailPresenter {

void display(String taskUuid);

}

151

Page 152: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 9 : Ajout/modification de la classe TaskConsultViewImpl.java

Ajouter/Modifier la classe suivante dans le package client.view :

public class TaskConsultViewImpl extends VerticalPanel implements TaskConsultView {

public TaskConsultViewImpl() {

}

@Overridepublic void reset() {clear();

}

@Overridepublic void display(Task task) {add(new Label(task.getDescription()));add(new Label(task.getResponsible()));add(new Label(task.getDeadLine().toString()));}

}

152

Page 153: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 10 : Ajout/modification de la classe TaskListView.java

Ajouter/Modifier la classe suivante dans le package client.view :

public interface TaskListView extends IsWidget {

void reset();

void displayTasks(ArrayList<Task> tasks);

void setPresenter(Presenter presenter);

public interface Presenter extends DetailPresenter {

}

}

153

Page 154: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 11 : Ajout/modification de la classe TaskListViewImpl.java

Ajouter/Modifier la classe suivante dans le package client.view :

public class TaskListViewImpl extends VerticalPanel implements TaskListView {

private Presenter presenter;

private TaskListPanel taskListPanel;

public TaskListViewImpl() {

super();

setWidth("100%");

getElement().getStyle().setMargin(5, Unit.PX);

getElement().getStyle().setBorderColor("white");

getElement().getStyle().setBorderWidth(2, Unit.PCT);

getElement().getStyle().setBorderStyle(BorderStyle.SOLID);

Heading title = new Heading(HeadingSize.H2);

title.setText("Task List");

add(title);

taskListPanel = new TaskListPanel();

add(taskListPanel);

}

@Override

public void reset() {

taskListPanel.reset();

}

@Override

public void setPresenter(Presenter presenter) {

this.presenter = presenter;

taskListPanel.setPresenter(presenter);

}

@Override

public void displayTasks(ArrayList<Task> tasks) {

taskListPanel.reset();

taskListPanel.setTasks(tasks);

}

}

154

Page 155: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 12 : Ajout/modification de la classeWelcomeView.java

Ajouter/Modifier la classe suivante dans le package client.view :

public interface WelcomeView extends IsWidget {

void reset();

void setRecentTask(ArrayList<Task> tasks);

void setPresenter(Presenter presenter);

public interface Presenter extends DetailPresenter {void addTask(Task task);

void showList();}}

155

Page 156: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 13 : Ajout/modification de la classeWelcomeViewImpl.java

Ajouter/Modifier la classe suivante dans le package client.view :

public class WelcomeViewImpl extends VerticalPanel implements WelcomeView {

private NewTaskCreationPanel taskCreationPanel;

private TaskListPanel taskListPanel;

private Presenter presenter;

public WelcomeViewImpl() {

super();

getElement().getStyle().setMargin(5, Unit.PX);

getElement().getStyle().setBorderColor("white");

getElement().getStyle().setBorderWidth(2, Unit.PCT);

getElement().getStyle().setBorderStyle(BorderStyle.SOLID);

taskCreationPanel = new NewTaskCreationPanel();

add(taskCreationPanel);

Button addButton = new Button("Add");

addButton.setIcon(IconType.PLUS);

addButton.setType(ButtonType.PRIMARY);

addButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

presenter.addTask(taskCreationPanel.flush());

}

});

add(addButton);

add(new Heading(HeadingSize.H2, "Latest"));

taskListPanel = new TaskListPanel();

add(taskListPanel);

Button taskListButton = new Button("View all");

taskListButton.getElement().getStyle().setMarginTop(5, Unit.PX);

taskListButton.setIcon(IconType.LIST);

taskListButton.setType(ButtonType.PRIMARY);

taskListButton.addClickHandler(new ClickHandler() {

@Override

public void onClick(ClickEvent event) {

presenter.showList();

}

});

add(taskListButton);

setWidth("98%");

}

@Override

public void reset() {

taskCreationPanel.reset();

taskListPanel.reset();

}

@Override

public void setRecentTask(ArrayList<Task> tasks) {

taskListPanel.setTasks(tasks);

}

@Override

public void setPresenter(Presenter presenter) {

this.presenter = presenter;

taskListPanel.setPresenter(presenter);

}

} 156

Page 157: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 14 : Ajout/modification de la classe TaskServiceImpl.java

Ajouter/Modifier la classe suivante dans le package server.service:

public class TaskServiceImpl extends RemoteServiceServlet implements TaskService {

ArrayList<Task> tasks = new ArrayList<>();

public TaskServiceImpl() {

fakeInit();

}

private void fakeInit() {

for (int i = 0; i < 10; i++) {

save(createTask(i));

}

}

@Override

public Task save(Task task) {

task.setUuid(UUID.randomUUID().toString());

tasks.add(task);

return task;

}

@Override

public ArrayList<Task> findLatest() {

int maxElementCount = 5;

int taskCount = tasks.size();

if (taskCount < maxElementCount) {

maxElementCount = taskCount;

}

ArrayList<Task> aux = new ArrayList<Task>(tasks.subList(taskCount - maxElementCount, taskCount));

Collections.reverse(aux);

return aux;

}

@Override

public ArrayList<Task> findAll() {

ArrayList<Task> aux = new ArrayList<Task>(tasks);

Collections.reverse(aux);

return aux;

}

public Task createTask(int count) {

Task result = new Task();

result.setResponsible("Resp. " + count);

result.setDescription("Description. " + count);

result.setDeadLine(new Date());

return result;

}

@Override

public Task findByUuid(String uuid) {

for (Task task : tasks) {

if (task.getUuid().compareTo(uuid) == 0) {

return task;

}

}

return null;

}

} 157

Page 158: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

EXERCICE 6 : MISE EN PLACE GWT-RPC

Etape 15 : Modification du fichierweb.xml

Modifier le fichier web.xml de la manière suivante:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5"xmlns="http://java.sun.com/xml/ns/javaee">

<!-- Servlets -->

<servlet><servlet-name>taskServlet</servlet-name><servlet-class>fr.jdev.atelier.server.service.TaskServiceImpl</servlet-class></servlet>

<servlet-mapping><servlet-name>taskServlet</servlet-name><url-pattern>/monapplication/tasks</url-pattern>

</servlet-mapping>

<!-- Default page to serve --><welcome-file-list>

<welcome-file>MonApplication.html</welcome-file></welcome-file-list>

</web-app>

158

Page 159: TP GWT JDEV 2015

CONCLUSION

Page 160: TP GWT JDEV 2015

Introduction Architecture Premiere application Creation de l’interfacegraphique Bus d’evenements Cinematique de l’appli-

cationCommunicationclient-serveur Conclusion

CONCLUSION

I Le framework GWT est extrêmement riche, d’autresfonctionnalités restent à aborder :

Mise en place du multilinguisme (I18n)Optimisation des ressources Image et StyleOptimisation des échanges Client/Serveur (RequestFactory )Inversion de contrôle côté client (GIN)Chargement du code client par tranche (Code spliting)Data Binding (Framework Editor )...

I De plus la mise en œuvre d’un projet GWT peut égalementnécessiter la connaissance de technologies complémentaires :

Architecture REST (SOAP)Responsive DesignGit & Gitflow...

160