Google Web Toolkit ( GWT )

quaggaholeInternet και Εφαρμογές Web

15 Αυγ 2012 (πριν από 4 χρόνια και 11 μήνες)

469 εμφανίσεις

(c) 2011, Occello Audrey, POO/IHM
Google Web Toolkit (GWT)
Concepts avancés

sa
(c) 2011, Occello Audrey, POO/IHM
-
2
-
Internationalisation
(c) 2011, Occello Audrey, POO/IHM
-
3
-

Supporter différents langages au niveau de l'IHM


Sans écrire N versions


Sans gros "switch" pour traiter les différents cas
directement dans le code


Cf vos cours d'OGL !
Gestion de l'internationalisation (i18n)
(c) 2011, Occello Audrey, POO/IHM
-
4
-

1. Ajouter la ligne suivante dans le fichier de config du module :
<inherits name="com.google.gwt.i18n.I18N"/>

2. Rechercher les éléments "internationalisables" (messages
d'information ou d'erreurs, nombres, dates qui sont communiqués à
l'utilisateur)

3. Créer les interfaces d’accès aux ressources internationalisées

4. Définir les fichiers de propriétés pour les traductions

5. Remplacer des chaines de caractères dans le code par l’utilisation des
interfaces d’accès

6. Indiquer les versions linguistiques à générer dans le fichier de
configuration

7. Paramétrer la langue pour l'utilisateur au niveau de la page web
d'intégration du module


Gestion de l'internationalisation en GWT
(c) 2011, Occello Audrey, POO/IHM
-
5
-

public class Hello implements EntryPoint {
public void onModuleLoad() {
final TextBox input = new TextBox();
final Button button = new Button("Click me");
button.setEnabled(false);
final HTML reply = new HTML();
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String name = input.getText().trim();
Window.alert("Dear "+name+", service not yet supported");

}
});
...
}
}
Rechercher les éléments du module Hello à
internationaliser
(c) 2011, Occello Audrey, POO/IHM
-
6
-

Permet de récupérer une chaine de caractères dans différentes
langues

On donne, dans une annotation, la valeur par défaut utilisée en cas de
non affectation de la propriété locale (qui détermine la langue
demandée par l'utilisateur)

package fr.polytech.hello.client;
import com.google.gwt.i18n.client.Constants;

public interface HelloConstants extends Constants {
@DefaultStringValue("Click me")
String buttonTitle();
}


Dear "+name+", service not yet supported" va être gérée
différemment car sinon il faudrait la traiter comme 2 chaines de
caractères !

Créer une interface d'accès aux chaines de
caractères constantes
(c) 2011, Occello Audrey, POO/IHM
-
7
-

Permet de récupérer une chaine de caractères qui comporte des
variables dans différentes langues

On donne là encore la valeur par défaut dans une annotation

package fr.polytech.hello.client;
import com.google.gwt.i18n.client.Messages;

public interface HelloMessages extends Messages {
@DefaultStringValue("Dear ''{0}'', service not yet
supported")
String alertCreate(String name);
}


''{0}'' represente la variable name


Note :
Il existe aussi deux classes pour gérer format de dates et de nombres
(DateTimeFormat et NumberFormat)
Créer une interface d'accès aux chaines de
caractères paramétrées
(c) 2011, Occello Audrey, POO/IHM
-
8
-

Autant de fichiers HelloConstants_XX.properties et
HelloMessages_XX.properties que de langues supportées

XX doit être remplacé par le code de la locale pour chaque
langue/région (fr, en, de, fr_CA, etc)

Le texte doit être sauvegardé avec encodage UTF-8
Définir les fichiers de propriétés pour les
traductions

HelloMessages_fr.properties :

alertCreate = Cher {0}, service pas encore supporte


HelloConstants_fr.properties :

buttonTitle = Cliquez moi

Attention, mêmes noms que
les méthodes définies dans
les interfaces
(c) 2011, Occello Audrey, POO/IHM
-
9
-

Le texte en anglais disparaît ...

public class Hello implements EntryPoint {
private HelloConstants constants = GWT.create(HelloConstants.class);
private HelloMessages messages = GWT.create(HelloMessages.class);

public void onModuleLoad() {
final TextBox input = new TextBox();
final Button button = new Button(constants.buttonTitle());
button.setEnabled(false);
final HTML reply = new HTML();
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String name = input.getText().trim();
Window.alert(messages.alertCreate(name));
}
});
...
}
}
Remplacer les chaines de caractères de la classe
Hello
(c) 2011, Occello Audrey, POO/IHM
-
10
-

Dans l'exemple suivant, deux versions du module sont générées :
celle par défaut (anglais dans notre cas) et la version française

Si l'on omet la partie bleue, seule la version par défaut sera générée

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit
1.6.4//EN" "http://google-web-
toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-
module.dtd">
<module rename-to='hello'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<inherits name="com.google.gwt.i18n.I18N" />

<entry-point class='fr.polytech.hello.client.Hello'/>

<extend-property name="locale" values="fr"/>
</module>

Indiquer les versions linguistiques à générer dans le
fichier de configuration
(c) 2011, Occello Audrey, POO/IHM
-
11
-

Dans l'exemple suivant, la page web sera chargée en version française

Si le français est demandé mais que cette version n'est pas supportée
ou qu'elle n'a pas été générée, la version par défaut sera chargée

Idem, si l'on omet la partie bleue, la version par défaut sera chargée
(implicitement équivalent à :
<meta name="gwt:property" content="locale=default"> )

On peut aussi spécifier la version désirée au niveau de l'URL en
ajoutant à la fin : "?locale=xx" (où xx représente fr, en, de, etc)

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="gwt:property" content="locale=fr">
<link type="text/css" rel="stylesheet" href="Hello.css">
<title>Hello</title>
<script type="text/javascript" language="javascript"
src="hello/hello.nocache.js"></script>
</head>
<body> ... </body>
</html>
Paramétrer la langue pour l'utilisateur au niveau de la
page web d'intégration du module
(c) 2011, Occello Audrey, POO/IHM
-
12
-
Communications avec le
serveur
(c) 2011, Occello Audrey, POO/IHM
-
13
-

Jusqu'à présent notre IHM Hello World ne fait pas grand
chose ...


Il faut pouvoir connecter les actions sur l'IHM à des
requêtes serveur pour récupérer la salutation une fois le
nom tapé

Ces traitements ne peuvent pas être faits coté client
car dépendent des données définies au niveau du
serveur
Et le serveur dans tout ça ?
(c) 2011, Occello Audrey, POO/IHM
-
14
-

Appels asynchrones équivalents au XMLhttpRequest
– via les classes RequestBuilder et RequestCallback


Mode RPC (Remote Procedure Call) – slides bonus à la fin
– offre la possibilité d’appeler des objets distants écrits en Java
– automatise la sérialisation des objets transmis
– format spécifique


Intégration Javascript via JSNI (JavaScript Native
Interface)
– Permet d'utiliser des bibliothèques Javascript

Le modèle de communication GWT
(c) 2011, Occello Audrey, POO/IHM
-
15
-

Utilisation des classes RequestBuilder et RequestCallback
– RequestBuilder permet de créer la requête
– RequestCallback permet de décrire le code à exécuter une fois
la requête traitée par le serveur


Il faut ajouter la ligne suivante dans le fichier de config
du module (Hello.gwt.xml) :
<inherits name="com.google.gwt.http.HTTP"/>


Il faut aussi importer le package correspondant dans la
classe créant et exécutant la requête
com.google.gwt.http.client
Appels asynchrones au serveur
(c) 2011, Occello Audrey, POO/IHM
-
16
-

public class Hello implements EntryPoint {
public void onModuleLoad() {
// Parties création de widget et layout (inchangées)
// Gestion des événements associés aux widgets
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// vers la création de la salutation
hello(input.getText());
}
});

input.addKeyUpHandler(new KeyUpHandler() {
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
// vers la création de la salutation
hello(input.getText());
}
});
}
}
Implémentation des actions pour le module Hello
Appels serveur
(c) 2011, Occello Audrey, POO/IHM
-
17
-
attention, les méthodes faisant des appels
asynchrones doivent être void (on ne peut savoir
quand on aura le résultat)





public void hello(final String name) {
final String url = GWT.getModuleBaseURL() + "data.txt";
RequestBuilder req = new RequestBuilder(RequestBuilder.GET, url);

try {
req.sendRequest(null, new RequestCallback() {
... // voir le code au prochain slide
});
} catch (RequestException e) {
reply.setHTML("exception: " + e.getMessage());
}
// plus rien à partir d’ici si une réponse du serveur est souhaitée
}
Implémentation de la méthode
hello

Le fichier data.txt
doit être déposé dans
le répertoire public

(c) 2011, Occello Audrey, POO/IHM
-
18
-

On précise le cas de retour normal et le cas d'erreurs

Le déclenchement de l’événement doit être fait DANS le callback et
pas après

req.sendRequest(null, new RequestCallback() {
public void onResponseReceived(Request request, Response response) {
String res = response.getText();
reply.setHTML(res+" "+ name);
}
public void onError(Request arg0, Throwable arg1) {
reply.setHTML("cannot contact server");
}
});


Code du
RequestCallback
pour
hello

(c) 2011, Occello Audrey, POO/IHM
-
19
-

Les appels distants peuvent provoquer de nombreuses
erreurs


Une exception de type Throwable est passée à la méthode
onError de l'objet callback coté client si :
– un appel distant ne peut aboutir (réseau coupé, problème de
DNS, arrêt du serveur HTTP)

– une exception est levée par une des méthodes java coté serveur

Quid de la gestion des exceptions
(c) 2011, Occello Audrey, POO/IHM
-
20
-
GWT & architecture
(c) 2011, Occello Audrey, POO/IHM
-
21
-
Comment séparer fonctionnalités et présentations ?

 Faire fonctionner MVC comme en SWING (cf TD 4) en :
 gardant les events et listeners de java.util

dérivant le modèle pour gérer les listeners et la transmission des
événements

 Faire fonctionner MVC en
 définissant des events et handlers propes à GWT et

utilisant le bus à événements intégré à GWT qui gére les listeners
et la transmission des événements


Utiliser le framework MVP intégré à GWT


Ces architectures ne concernent que la partie «

client

»
du module

(c) 2011, Occello Audrey, POO/IHM
-
22
-

Utilisation des classes/interfaces du package
com.google.gwt.event.shared

Dispatches GwtEvents to interested parties. Eases decoupling by allowing
objects to interact without having direct dependencies upon one another, and
without requiring event sources to deal with maintaining handler lists.” -
javadoc

Etapes à suivre :

Définition de l’événement : hériter de GwtEvent, ajouter les données que l’on
souhaite transférer à l’écouteur et implémenter les méthodes dispatch
(transmission de l’événement à l’écouteur) et getAssociatedType
(identificateur de l’événement)

Définition de l’écouteur associé : hériter de EventHandler et définir la
méthode que l’écouteur doit implémenter

Définition du bus : Créer un objet de type EventBus et lui indiquer quel
écouteur écoute quel événement pour quelle source (méthode
addHandlerToSource)

Définition des points de déclenchement de l’événement : Au niveau de la
source déclencher un événement (méthode fireEventFromSource du bus)
Utilisation du bus à événements
(c) 2011, Occello Audrey, POO/IHM
-
23
-
Le point d’entrée du module Hello
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.event.shared.HandlerRegistration;
public class HelloMVC implements EntryPoint, CloseHandler<Window> {
public static EventBus bus;
private HandlerRegistration hr;
static {
bus = new SimpleEventBus();
}
public void onModuleLoad() {
Model model = new Model();
View view = new View("Click me");
Controller controller = new Controller(model, vue);
view.bind(controller);
hr = bus.addHandlerToSource(HelloEvent.getType(), model, view);
Window.addCloseHandler(this);
RootPanel.get().add(view);
}
// pour arreter l’écoute proprement
public void onClose(CloseEvent<Window> event) { hr.removeHandler(); }
}
“There will typically be one
EventBus per application,
broadcasting events that
may be of general interest”
- javadoc

(c) 2011, Occello Audrey, POO/IHM
-
24
-
Evénement & handler personnalisés du module Hello


public class HelloEvent extends GwtEvent<HelloHandler> {
private String msg;
private static final
Type<HelloHandler> TYPE = new Type<HelloHandler>();

public HelloEvent(String str) {
msg = str;
}

protected void dispatch(HelloHandler handler) {
handler.onHello(this);
}

public com.google.gwt.event.shared.GwtEvent.Type<HelloHandler>
getAssociatedType() {
return TYPE;
}

public static com.google.gwt.event.shared.GwtEvent.Type<HelloHandler>
getType() {
return TYPE;
}

public String getMsg() {
return msg;
}
}


public interface HelloHandler extends EventHandler {
public void onHello(HelloEvent le);
}

(c) 2011, Occello Audrey, POO/IHM
-
25
-
La vue du module Hello
public class View extends Composite implements HelloHandler {
private TextBox input;
private Button button;
private HTML reply;

public View(String buttonTitle) {
input = new TextBox();
button = new Button(buttonTitle);
reply = new HTML();
HorizontalPanel panel1 = new HorizontalPanel();
panel1.add(input);
panel1.add(reply);
VerticalPanel panel2 = new VerticalPanel();
panel2.add(panel1);
panel2.add(button);
initWidget(panel2);
}

public void bind(Controller controller) {
// voir page suivante
}

public void onHello(HelloEvent le) { reply.setHTML(le.getMsg()); }
}
(c) 2011, Occello Audrey, POO/IHM
-
26
-
Lien vue-contrôleur
public class Controller {
private Model model;
private View vue;
public Controller(Model m, View v) { model = m; vue = v; }
public void hello(String name) { model.hello(name); }
}
public class View extends Composite implements HelloHandler {
...
public void bind(Controller controller) {
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
controller.hello(input.getText().trim());
}
});

input.addKeyUpHandler(new KeyUpHandler() {
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
controller.hello(input.getText().trim());
}
});
}
}
(c) 2011, Occello Audrey, POO/IHM
-
27
-
Lien vue-contrôleur
public class Controller {
private Model model;
private View vue;
public Controller(Model m, View v) { model = m; vue = v; }
public void hello(String name) { model.hello(name); }
}
public class View extends Composite implements HelloHandler {
...
public void bind(Controller controller) {
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
controller.hello(input.getText().trim());
}
});

input.addKeyUpHandler(new KeyUpHandler() {
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
controller.hello(input.getText().trim());
}
});
}
}
Pour une meilleure séparation
vue-contrôleur, remplacer les
appels directs au contrôleur par
le déclenchement d’événements
de plus haut niveau auxquels
réagit le contrôleur
(c) 2011, Occello Audrey, POO/IHM
-
28
-
Le modèle du module Hello
public class Model {

public void hello(final String name) {
final String url = GWT.getModuleBaseURL() + "data.txt";
RequestBuilder req = new RequestBuilder(RequestBuilder.GET, url);
try {
RequestCallback mycallback = new RequestCallback() {
public void onResponseReceived(Request request, Response
response) {
String res = response.getText();
HelloEvent he = new HelloEvent(res+" "+ name);
HelloMVC.bus.fireEventFromSource(he, Model.this);
}

public void onError(Request arg0, Throwable arg1) {
HelloEvent he = new HelloEvent("cannot contact server");
HelloMVC.bus.fireEventFromSource(he, Model.this);
}
};
}
}
(c) 2011, Occello Audrey, POO/IHM
-
29
-
Comment séparer fonctionnalités et présentations ?

 Faire fonctionner MVC comme en SWING (cf TDs) en :
 gardant les events et listeners de java.util

dérivant le modèle pour gérer les listeners et la transmission des
événements

 Faire fonctionner MVC en
 définissant des events et handlers propes à GWT et

utilisant le bus à événements intégré à GWT qui gére les listeners
et la transmission des événements


Utiliser le framework MVP intégré à GWT


Ces architectures ne concernent que la partie «

client

»
du module

(c) 2010, Occello Audrey, POO/IHM
MVC & MVP
http://code.google.com/intl/fr/webtoolkit/articles/mvp-architecture.html
(c) 2011, Occello Audrey, POO/IHM
-
31
-
MVC et types d’application
Application "desktop" (entièrement hébergée sur le poste de travail)
Application web
classique
Données
M V C
M V C
contacts
M' V C (traitements de
données locaux)
Données
client
personnes
groupes
serveur
Application web
“riche”
M (traitements de données
lourds)
Données
client
serveur
réseau
réseau
V' (affichage)
(c) 2011, Occello Audrey, POO/IHM
-
32
-
Conclusion
(c) 2011, Occello Audrey, POO/IHM
-
33
-

Gestion de l’historique
– Interaction avec la pile du navigateur
– webAppCreator ajoute pour vous ce qu'il faut dans la page web
par défaut pour mémoriser la pile
– Par contre il faut gérer les événements associés
History.addValueChangeHandler(...);


Gestion du style : chaque type de widget correspond à une
classe css (cf javadoc) manipulable via le code java


Gestion de l'accessibilité (a11y) : des propriétés DOM pour
“décrire" et bien traiter les événement de chaque noeud
de la page web (W3C ARIA)
En bref : Tour d'horizon des autres fonctionnalités

(c) 2011, Occello Audrey, POO/IHM
-
34
-

Speed up the edit/refresh cycle with new development
mode


Create UIs declaratively with UiBinder


Produce pixel-perfect visuals with layout panels :
RootLayoutPanel, LayoutPanel, DockLayoutPanel,
SplitLayoutPanel, StackLayoutPanel, and TabLayoutPanel.


Speed application startup with developer-guided code
splitting (GWT.runAsync() )


Optimize resource downloads with ClientBundle
Améliorations dans GWT 2.x
(c) 2011, Occello Audrey, POO/IHM
-
35
-

Facilité de mise en oeuvre : le tout en java
– Pas besoin d'apprendre javascript
– Le typage statique de Java permet la detection des erreurs au plus tôt
– Utilisable au sein des IDE
– Le mode “development” facilite le test (pas besoin de redéployer à
chaque fois)
– Unification des technologies nécessaires au développement d'appli web
– Déploiement standard (répertoire war) depuis la version 1.6


Facilité d’extensiblilité : ajout d’API java tout simplement (Smart
GWT, GWT Rialto, GWT Widget, GWTaculous, MyGWT, ...)


Ouverture : integration des librairies javascript via JSNI


Pérennité
: stabilité du code + projet opensource (licence apache) + une
communauté active
Les avantages de GWT
(c) 2011, Occello Audrey, POO/IHM
-
36
-

Tout java n'est pas traductible en javascript


Programmation asynchrone un peu déroutante
– Pour réaliser un traitement séquentiel il faut faire des callbacks
imbriqués



Pas de support des scripts coté serveur (php, jsp, etc)
dans le mode “development”


Quid du passage à l'échelle (taille du fichier js
proportionnel au nombre de classes coté client)
– Améliorations attendues avec GWT.runAsync (GWT 2)

Les limites de GWT
(c) 2011, Occello Audrey, POO/IHM
-
37
-

Nécessite l'activation de l'option JavaScript du navigateur


Complique les comportements habituels du navigateur
(bookmarks, boutons précédent/suivant, etc)


Génère des problèmes de compatibilité navigateurs


Nécessite la connaissance de plusieurs technologies
Javascript, DOM, XMLHttpRequest, …


Peut conduire à des architectures très complexes

 Qu'en est il des autres approches RIAs ?
Conclusion générale sur Ajax
(c) 2011, Occello Audrey, POO/IHM
-
38
-
Pour ceux qui veulent aller plus loin ...
Supplément du cours :
Le modèle de communication
GWT/RPC
(c) 2011, Occello Audrey, POO/IHM
-
39
-

Appels asynchrones à un objet java distant (servlet ou
service GWT)


Communication RPC mais une autre technologie que Java
RMI


Hebergement coté serveur

Utilisation d’un service GWT
(c) 2011, Occello Audrey, POO/IHM
-
40
-

1ère étape : créer les interfaces d'accès au service hébergé par le
serveur web (YourService, YourServiceAsync)

2ième étape : implémenter le service (YourServiceImpl)

3ième étape : faire un appel au service (dans une des classes clientes)
Schéma à respecter pour communiquer en RPC
(c) 2011, Occello Audrey, POO/IHM
-
41
-

Les nouveaux fichiers à créer sont :
HelloService.java (coté client)
HelloServiceAsync.java (coté client)
HelloServiceImpl.java (coté serveur)


Les fichiers à modifier sont :
Hello.java et web.xml

Application du schéma RPC pour le module Hello
(c) 2011, Occello Audrey, POO/IHM
-
42
-

La méthode appelée dans le code client est hello
Créer les interfaces d'accès au service de
salutation
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
* The async counterpart of <code>HelloService</code>.
*/
public interface HelloServiceAsync {
void hello(String name, AsyncCallback<String> callback);
}
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
String hello(String name);
}
(c) 2011, Occello Audrey, POO/IHM
-
43
-

La méthode appelée dans le code client est hello
Créer les interfaces d'accès au service de
salutation
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
* The async counterpart of <code>HelloService</code>.
*/
public interface HelloServiceAsync {
void hello(String name, AsyncCallback<String> callback);
}
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
String hello(String name);
}
Le nom de la ressource web
correspondant au service
Sera utilisé dans le fichier
de déploiement web.xml
(c) 2011, Occello Audrey, POO/IHM
-
44
-

La méthode appelée dans le code client est hello
Créer les interfaces d'accès au service de
salutation
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
* The async counterpart of <code>HelloService</code>.
*/
public interface HelloServiceAsync {
void hello(String name, AsyncCallback<String> callback);
}
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
String hello(String name);
}
Attention à ne pas
oublier cet extends
(c) 2011, Occello Audrey, POO/IHM
-
45
-

La méthode appelée dans le code client est hello
Créer les interfaces d'accès au service de
salutation
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
* The async counterpart of <code>HelloService</code>.
*/
public interface HelloServiceAsync {
void hello(String name, AsyncCallback<String> callback);
}
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
String hello(String name);
}
La méthode peut renvoyer
n'importe quel type primitif
encapsulé ou classe sérialisable
Le type AsyncCallback doit être
paramétré avec le même type que
le type de retour dans l'autre
interface pour la méthode
correspondante
(c) 2011, Occello Audrey, POO/IHM
-
46
-

La méthode appelée dans le code client est hello
Créer les interfaces d'accès au service de
salutation
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
* The async counterpart of <code>HelloService</code>.
*/
public interface HelloServiceAsync {
void hello(String name, AsyncCallback<String> callback);
}
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
String hello(String name);
}
Le type de retour des méthodes
définies dans une interface
xxxAsync est toujours
void

Un appel asynchrone ne renvoie
jamais rien
(c) 2011, Occello Audrey, POO/IHM
-
47
-

La classe HelloServiceImpl remplace le fichier data.txt

La méthode que la classe serveur doit implémenter est hello


Implémenter le service de salutation
package fr.polytech.hello.server;

import fr.polytech.hello.client.HelloService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
* The server side implementation of the RPC service.
*/

public class HelloServiceImpl extends RemoteServiceServlet
implements HelloService {

public String hello(String name) {
return "Bonjour";
}
}

(c) 2011, Occello Audrey, POO/IHM
-
48
-

Etapes liées à l’utilisation d’un service GWT
– Créer un proxy (représentation du service coté client) :
objet de type XXXServiceAsync) en utilisant
GWT.create()
– Créer un callback (de type AsyncCallback cette fois)
activé lorsque le service aura terminé de traiter la
demande
– Faire l'appel à la méthode du service souhaitée et
passer le callback en dernier paramètre

Utiliser un service GWT
(c) 2011, Occello Audrey, POO/IHM
-
49
-

La classe cliente Hello fait appel au service au niveau du handler
Faire appel au service de salutation dans Hello
import com.google.gwt.user.client.rpc.AsyncCallback;
public class Hello implements EntryPoint {
// attribut representant le service distant
private final HelloServiceAsync helloService =
GWT.create(HelloService.class);
public void onModuleLoad() {
// création des widgets
// layout

// gestion des événements associés aux widgets
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// code appelant le service de salutation (cf page suivante)

}
});

input.addKeyUpHandler(new KeyUpHandler() {
public void onKeyUp(KeyUpEvent event) {
if ((event.getNativeKeyCode() == KeyCodes.KEY_ENTER) &&
button.isEnabled())
// code appelant le service de salutation (cf page suiv.)
}
});
}
}
(c) 2011, Occello Audrey, POO/IHM
-
50
-
Faire appel au service de salutation dans Hello
String name = input.getText().trim();

// Définition du callback
AsyncCallback<Boolean> mycallback=new AsyncCallback<Boolean>()
{
public void onFailure(Throwable caught) {
// traitement des erreurs
}

public void onSuccess(Boolean result) {
// traitement du résultat
}
});

// Appel au service
helloService.hello(name, mycallback);
(c) 2011, Occello Audrey, POO/IHM
-
51
-

Il faut indiquer comment récupérer la ressource correspondant au
service de salutation
Impact sur le fichier de déploiement
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>Hello.html</welcome-file>
</welcome-file-list>

<!-- Servlets -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>
fr.polytech.hello.server.HelloServiceImpl
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello/hello</url-pattern>
</servlet-mapping>
</web-app>
(c) 2011, Occello Audrey, POO/IHM
-
52
-

Il faut indiquer comment récupérer la ressource correspondant au
service de salutation
Impact sur le fichier de déploiement
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>Login.html</welcome-file>
</welcome-file-list>

<!-- Servlets -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>
fr.polytech.hello.server.HelloServiceImpl
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello/hello</url-pattern>
</servlet-mapping>
</web-app>
package fr.polytech.hello.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("hello")
public interface HelloService extends RemoteService {
Boolean hello(String name);
}
(c) 2011, Occello Audrey, POO/IHM
-
53
-


Principes similaires que pour les requêtes XMLHttp ...
Quid de la gestion des exceptions
(c) 2011, Occello Audrey, POO/IHM
-
54
-
Bilan communications réseaux ...