GWT : Création de l’applicatif (partie client)
|Notre application n’est pour l’instant peut-être pas très jolie, mais elle a l’avantage de contenir tous les conteneurs et commandes nécessaires pour recevoir les données et actions. Vous pouvez télécharger l’application en version 0.1 avant de commencer cet article.
Objet metier
Dans le projet GWTwitter, l’objet métier est le Tweet. Il doit contenir, pour le moment, un texte et une date. Par la suite nous lui rajouterons d’autres attributs. Mais pour l’instant créons cette classe dans le package « client ». Cet objet métier va circuler entre le serveur (AppEngine par exemple) et le client (un navigateur), c’est pourquoi il doit implémenter l’interface Serializable ou l’interface IsSerializable et doit avoir un constructeur sans paramètre.
package me.gwtwitter.client; import java.util.Date; import com.google.gwt.user.client.rpc.IsSerializable; public class Tweet implements IsSerializable { private String text; private Date date; public Tweet() {} public Tweet(String text) { this.text = text; this.setDate(new Date()); } public String getText() { return text; } public void setText(String text) { this.text = text; } public void setDate(Date date) { this.date = date; } public Date getDate() { return date; } }
RemoteService
Passons maintenant au RPC (Remote Procedure Call), en français : « L’appel de procédures distantes ». En effet nous allons, dans la partie client, appeler des méthodes « serveur » comme si elles étaient du côte client. Pour être plus précis, l’interface se trouve du côté « client » et l’implémentation se trouve du côté « serveur ». Deux interfaces nous intéresse :
- GWTwitterService qui étend com.google.gwt.user.client.rpc.RemoteService
- GWTwitterServiceAsync qui est étroitement liée à GWTwitterService
La première est l’interface principale, c’est elle qui va définir les méthodes RPC utilisables, leurs paramètres et leurs types de retour. La deuxième correspond à la version « asynchrone » de la première. Nous la ferons se générer toute seule.
GWTwitterService
Elle étend l’interface RemoteServce (RemoteService). Nous définirons 2 méthodes :
- boolean newTweet(String text);
- List<Tweet> tweets();
package me.gwtwitter.client; import java.util.List; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("twitter") public interface GWTwitterService extends RemoteService { void newTweet(String text); List<Tweet> tweets(); }
GWTwitterServiceAsync
Pensez à enregistrer la classe ci-dessus. Vous devez maintenant voir apparaître une indication qui vous dit que 2 méthodes doivent être déclarées dans GWTwitterServiceAsync.
Il vous suffit de cliquer sur l’indication et de choisir de générer la méthode.
package me.gwtwitter.client; import java.util.List; import com.google.gwt.user.client.rpc.AsyncCallback; public interface GWTwitterServiceAsync { void newTweet(String text, AsyncCallback<Void> callback); void tweets(AsyncCallback<List<Tweet>> callback); }
Un peu de code
Maintenant que nos interfaces sont prêtes, on va pouvoir les utiliser dans notre module : GWTwitter.
ServiceAsync
Le ServiceAsync a été mis en place juste ci-dessus. Pour l’utiliser, nous allons créer un attribut de type GWTwitterServiceAsync dans notre module :
public class GWTwitter implements EntryPoint { private final GWTwitterServiceAsync twitterService = GWT.create(GWTwitterService.class); /* Le reste de notre module */ }
Cet objet nous permettra d’appeler de façon asynchrone nos RPC.
RefreshTweetsTable
Créons ensuite, dans la classe GWTwitter, une méthode nommée refreshTweetsTable qui ne retourne rien et qui n’attends rien. Elle aura pour but de d’appeler la RPC créée ci-dessus puis de présenter les tweets dans la FlexTable.
Pour appeler notre RPC il faut faire utiliser le ServiceAsync créé ci-dessus : List<Tweet> twitterService.tweets(AsyncCallback<List<Tweet>> callback).
twitterService.tweets(new AsyncCallback<List<Tweet>>() { @Override public void onSuccess(List<Tweet> result) { // Ici tout va bien, on peut présenter les données } @Override public void onFailure(Throwable caught) { // Ici il y a eu une erreur } });
Nous allons, pour le moment, nous occupé uniquement du onSuccess, c’est à dire de remplir la FlexTable.
FlexTable tweetsTable = new FlexTable(); tweetsTable.setText(1, 2, "Un petit text"); tweetsTable.setWidget(1, 1, new Button("Un bouton"));
int i = 0; for(Tweet t : result) { tweetsTable.setText(++i, 0, DateTimeFormat.getMediumDateTimeFormat().format(t.getDate())); tweetsTable.setText(i, 1, t.getText()); }
Puis on affiche la date du moment afin d’indiquer la dernière mise à jour des données.
updateLabel.setText(DateTimeFormat.getMediumDateTimeFormat().format(new Date()));
Le tour est joué !
SubmitNewTweet
Maintenant que nous sommes capable d’afficher la liste nous tombons face à un énorme problème… Impossible de tester car il n’y a aucun Tweet de créé pour le moment.
Le principe est simple. Nous allons tout d’abord créer la méthode qui récupèrera le texte du nouveau Tweet puis l’enverra au serveur via la seconde RPC : void twitterService.writeTweet(AsyncCallback<Void> callback).
Pas besoin de tout vous expliquer à nouveau. Ici nous appliquons le même principe qu’avec l’autre RPC vue ci-dessus.
private void submitNewTweet(String text){ twitterService.newTweet(text, new AsyncCallback() { @Override public void onSuccess(Boolean result) { tweetTextBox.setText(""); refreshTweetsTable(); } @Override public void onFailure(Throwable caught) { // Ici il y a eu une erreur } }); }
ClickHandler et KeyPressHandler
ClickHandler et KeyPressHandler sont deux interfaces. La première permet de réagir au clic de la souris, la deuxième à une touche appuyée (la touche « entrée » dans notre cas).
Nous allons créer une classe interne qui implémentera les deux interfaces et donc qui réagira dans les deux cas présentés ci-dessus. Cette aura deux méthodes (onClick et onKeyPress) qui appelleront toutes les deux la méthode créée précédemment (submitNewTweet).
public class GWTwitter implements EntryPoint { // Ici il y a tout le reste de notre classe. // Je ne l'affiche pas pour plus de clarté. private class MyHandler implements ClickHandler, KeyPressHandler { @Override public void onClick(ClickEvent event) { submitNewTweet(tweetTextBox.getText()); } @Override public void onKeyPress(KeyPressEvent event) { if(event.getCharCode() == 13){ submitNewTweet(tweetTextBox.getText()); } } } }
Pour finir avec ce Handler, nous devons l’associer à notre champ texte et à notre bouton :
public void onModuleLoad() { MyHandler myHandler = new MyHandler(); submitButton.addClickHandler(myHandler); tweetTextBox.addKeyPressHandler(myHandler); /* Le reste de onModuleLoad() */ }
Nous voilà arrivé à la fin de cette partie. Nous avons mis en place toute (ou presque toute) la partie client de notre application. Il ne nous reste qu’à mettre en place le code du côté serveur pour avoir un projet qui fonctionne.
Vous pouvez télécharger la Version de développement 0.2 de GTWitter pour tester le résultat chez vous.
Prochaine partie : Création de l’applicatif (partie serveur).







