vendredi 27 août 2010

[GWT] Tutoriel AJAX

Bonjour,                                                                                        GWT V2.0.4
Pour commencer à toucher au modèle MVC, on va se pencher sur la réalisation d'une calculatrice respectant le modèle MVC et  appelant le serveur pour ce qui est du calcul de factorielles.
Dans un premier temps, on va faire une calculatrice non ajax, seulement coté client.
Je vous conseille de faire maintenant un petit diagramme de classe faisant apparaitre correctement les cotés Model, View et Controller ainsi que les interfaces implémentées ou les classes mères.
On rajoutera dans la partie 2 les appels RPC (AJAX)
Voici mon diagramme de classe, celui qu'on utilisera lors de ce tuto :


On va donc créer une nouvelle application GWT, (voir le tuto précédent) puis on va créer de nouveaux packages à ceux déjà existant.

Ainsi dans le package com.client, on va créer 3 packages : model, view, controller.

Cela nous créé notre modèle MVC.
On va d'abord créer le MODELE Calculator.
1) Clic droit sur le package, new-> class; entrer Calculator comme nom de classe puis valider.
2)  sur notre schéma on a déclaré 4 constantes, définissant les modes de calcul disponible de la calculatrice. On a aussi une "proprieté" mode qui définit le mode courant.
La proprieté oldValue est le résultat de l'opération précédente.
La proprieté currentValue correspond au nombre dernierement ajouté.
La proprieté saveCurrentValue est un booléen qui va gérer l'ajout ou le remplacement des chiffres à l'écran. Ainsi, la première touche, au départ et après une opération, remplacera le résultat et le booléen passera à false jusqu'à ce que l'on clique sur un opérateur (+ - * / = ).

3) Les méthodes ! On déclare un constructeur Calculator(); Rien de méchant, le constructeur va servir à instancier (créer) un nouveau calculator.
On va ensuite déclarer un méthode appendDigit(int value) qui va être appellée lors du clic sur un bouton numérique (0-9) et va servir à remplacer le résultat à l'écran ou à le mettre à la suite (en fonction du booléen saveCurrentValue).
La méthode clear() va servir à purger notre calculatrice, c'est litteralement un remise à zéro RAZ, déclenchée lorsqu'on clique sur le bouton C.
La méthode compute() va calculer notre opération. En fonction du mode (ADD=>0,SUBSTRACT=>1,MULTIPLY=>2,DIVIDE=>3)
la méthode getOldValue() est juste un accesseur, pas besoin d'en parler plus longuement.

On va maintenat créer la VUE CalculatorWidget.
Celle-ci va nous permettre de générer notre clavier, notre écran, bref notre calculatrice coté utilisateur.

1) On a une proprieté screen qui va définir l'écran dans lequel l'utilisateur verra affiché la réponse.
2) On ajoute ensuite les méthodes. On a une méthode pour afficher quelque chose à l'écran, une méthode pour créer une touche : createButton(), une autre pour le clavier : createKeyboard() qui va utiliser la méthode createButton().
Mais avez vous remarqué que notre CalculatorWidget hérite de SimplePanel.
Notre widget sera donc un SimplePanel et on veut que lorsqu'on le charge, on génère un VerticalPanel dans lequel on ajoute screen (TextBox) qu'on désactive pour ne pas qu'on puisse y taper n'importe quoi, et qu'on génère un clavier pour pouvoir demander un calcul.
On ordonne ces actions dans la méthode @override onLoad()

La fonction display() est bateau, pas besoin d'un dessin, je la met quand même pour plus de clarté.

On va enfin créer le CONTROLLEUR ButtonHandler.


1) Le controlleur est la pièce directrice de votre programme. C'est ici que l'on va créer notre modèle et notre vue et que l'on va effectuer les actions au clic des boutons.
Ainsi, on va faire implémenter l'interface ClickHandler et on va donc implémenter l'action onClick() afin de définir le comportement du programme et donc calculer les opérations et recharger l'affichage de l'écran.

On pourrait presque penser que c'est fini et c'est presque vrai !

Il faut maintenant changer ce que fait le programme, le main si vous venez du Java. En GWT, vous l'avez compris, on appelle ça le onModuleLoad() :


                                                                                                                          
ACTION AJAX
                                                                                                                          
On va essayer d'expliquer le plus facilement possible les concepts de base. 
Pour intégrer de l'AJAX dans notre calculatrice, on va ajouter une nouvelle fonctionnalité : la factorielle.
C'est peut être pas très clair pour ce qu'est la factorielle alors je vous le dis la factorielle de 5, c'est 1x2x3x4x5 donc c'est pas forcément très dur mais ca monte très vite dans des nombres énormes.

GWT fournit un framework complet reposant sur un modèle entièrement asynchrone.
Voilà comment s'articule le moteur RPC :




L’interface de service est le contrat de notre service. C’est l’ensemble des opérations que nous proposons de distribuer. Il existe deux types d’interface.
• L’interface synchrone (MyService/FactoService) : c’est cette interface qui est utilisée par notre implémentation sur le serveur. Elle est générée en JavaScript lors de la phase de compilation et se
situe côté client du fait de sa dépendance avec d’autres éléments côté client.
• L’interface asynchrone : dans GWT, toute requête Ajax s’effectue de manière asynchrone. C’est cette interface qui est concrètement utilisée lors de l’invocation par le code client.


1) On va donc créer notre interface de synchrone. On va la nommer FactoService et la faire étendre de RemoteServiceServlet
    On déclare la méthode pour calculer la factorielle. On va l'appeller factoServer(int n)
    Il faut ensuite assigner à notre servlet un alias en ajoutant @RemoteServiceRelativePath("facto") au dessus de la déclaration de l'interface


2) Puis l'autre interface, l'asynchrone. On va la nommer, et c'est obligatoire de la nommer comme ceci NomDeLInterfaceSynchrone+Async, ce qui donne FactoServiceAsync




3) Comme vous le voyez sur le schéma au dessus, on doit générer un proxy. Le Proxy va servir à communiquer entre le client et le serveur. Sur le schéma, il y a marqué "Généré", Java nous permet de créer dynamiquement des classes. On appelle la méthode create de la final Class GWT en lui passant le nom de l'interface FactoService et le type FactoServiceAsync. Il faut mettre cette ligne de code dans le modèle ou l'on veut éffectuer l'action AJAX (on peut cependant le mettre ailleurs si on en a besoin ailleurs, tant que ca respecte le modèle MVC).
Voici la fameuse ligne de code :



4) Le mécanisme RPC est quasiment fini coté client. Il faut maintenant créer la méthode dans notre modèle. Je vous rappelle le but de l'action AJAX, c'est trouver la factorielle d'un nombre.
Donc dans notre modèle Calculator, on va ajouter une méthode askFactoToServer(int n)


On a bouclé tout ce qui se trouve du coté client.
Une classe reste désormais à implémenter, la classe coté serveur.

5) Sur le schéma, on voit la classe MyServiceImpl.java, c'est la classe coté serveur qui va nous calculer notre factorielle.



on ajout @suppressWarnings("serial") pour éviter un avertissement lié à la sérialisation

Et voilà ! Profitez bien !

mardi 17 août 2010

[GWT] Tutoriel de découverte

Me voilà dans un nouveau stage !
Je travaille pour un professeur qui souhaite créer un logiciel en ligne d'exercice de maths, de suivi des élèves et de gestion de compétences.
On va normalement travailler avec Google web toolkit !
C'est avec ce toolkit que Google code ses applications et le concept est assez simple et interessant :
- Ce n'est que du JAVA !
Je ne sais pas si c'est une bonne nouvelle mais c'est comme ca :D

Le fonctionnement est donc que l'on code tout en Java en utilisant les librairies qui conviennent. On ne touche normalement jamais à une ligne de code js et c'est completement objet.
J'ai donc installé ça ce soir et ca me donne très envie aussi je vous le recommande, je vais m'y mettre serieusement là et je posterais quelques tutoriels à ce sujet.
Ci contre un premier screen de ce qu'un projet neuf donne :

Je vous propose maintenant un petit tuto de découverte de GWT :
c'est fortement inspiré du tuto que propose google ici : StockWatcher
                                                                                                                             
Il faut tout d'abord installer eclipse si vous ne l'avez pas déjà fait.
1. téléchargez la dernière version d'eclipse sur http://www.eclipse.org/downloads/
2. ensuite allez dans Eclipse -> Help -> New Software
Une fois dans New Software, on ajoute cet url : http://dl.google.com/eclipse/plugin/3.5 qui contient les sources de GWT et le plugin GWT pour eclipse
3. Cochez  tout
4. Continuez l'installation jusqu'à la fin, logiquement pas de problème sinon suivez ce qu'ils disent, puis redémarrer.
5. De nouvelles choses apparaissent désormais , notamment 3 icones avec le g emblématique de google.
6. Eclipse vient d'installer GWT et être maintenant prêt à l'utiliser.
                                                                                                                             
Je vais fonctionner ici en captures d'écran pour le code pour ne pas que vous copiez (bêtement) le code car c'est incomparable la différence entre écrire le code et le copier pour la compréhension.
On créer maintenant une nouvelle application web google. C'est assez instinctif, c'est cette icone . 
On renseigne le nom du projet :stockWatcher et le package, habituellement, je mets juste com
Ca génère donc le hello world, c'est assez marrant, ca montre un peu comment ca s'organise mais ca ne sert pas à grand chose.


On va maintenant dans war et on ouvre le fichier stockwatcher.html (ca dépend du nom que vous avez pris pour votre nom de projet, j'ai moi pris "stockwatcher") puis on fait le ménage, rien qu'en enlevant les commentaires, on arrive à un truc propre et simple :
<!doctype html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="StockWatcher.css">
    <title>Web Application Starter Project</title>
    <script type="text/javascript" language="javascript" src="stockwatcher/stockwatcher.nocache.js"></script>
  </head>
  <body>
    <h1>StockWatcher</h1>
    <div id="stockList"></div>
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
  </body>
</html>


GWT utilise les id pour dire ou il veut afficher ses élements. Ainsi, on a fait une div avec l'id stockList vide mais dans le but d'y mettre notre contenu.
on ouvre maintenant com.client.StockWatcher.java
On a notre classe, déclarée comme ceci : public class StockWatcher implements Entrypoint{ } 
Je vous rappelle qu'on déclare ce dont on a besoin directement dans la classe.


Dans ce tuto, on veut pouvoir ajouter en Ajax de nouvelles entrées dans un tableau, on va donc avoir besoin :

  • d'un tableau (flexTable)
  • d'un input text (TextBox) 
  • d'un label pour indiquer la date de dernière mise à jour (Label)
  • d'un bouton (Button)
On a aussi besoin d'un panel, c'est typique de Java, considerons le simplement comme un socle.

  • un panel pour l'affichage (VerticalPanel) et un panel horizontal pour l'ajout d'entrées
Mais tous ces éléments nécessitent l'import de certains fichiers.
On met ces import de librairies tout en haut du fichier.
Donc on met ca juste en dessous de la déclaration de la classe.



Le point d'entrée du programme, c'est la fonction public void onModuleLoad(){ }

C'est notre "main" pour ceux qui le cherchaient...
On commence par créer notre tableau dans lequel on va stocker les données, c'est le FlexTable stocksFlexTable :

Cela fera 4 colonnes.

On va ensuite y mettre l'input text et le bouton pour pouvoir ajouter des nouvelles entrées dans l'horizontalPanel addPanel:


Maintenant on met dans le mainPanel le tableau, le panel d'ajout d'entrées ainsi que notre label de mise à jour :


Vient ensuite une chose très interessante, la notion de RootPanel.
Le RootPanel, c'est notre page ! On ne la déclare jamais, elle est omniprésente et sert à communiquer entre notre classe et notre fichier html.

Ainsi, on va mettre notre mainPanel dans la div d'id stocksList comme ceci :



Maintenant, si on appuye sur F11 dans eclipse, on build notre projet et on peut le visualiser dans notre navigateur préféré (sauf au moment ou j'écris sur chrome sous ubuntu, c'est un comble !! Google quand même :S )

Mais pour l'instant, rien ne se passe en cliquant sur notre bouton et le tableau est vide.
Il faut créer une action sur le clic du bouton pour pouvoir envoyer le contenu de l'input text vers le flexTable.

Cela se fait avec la méthode addClickHandler de notre objet addStockButton.


Vous voyez ici que l'on fait appel, dès que l'on clique sur le bouton addStockButton, la fonction addStock();  Or cette fonction n'éxiste pas et eclipse va vous le faire remarquer.
Eclipse est sympa ! Il va même vous proposer de la créer à votre place.

Imaginons qu'on ne veuille pas ajouter 2 fois la même chose dans notre FlexTable et seulement des entrées de plus de 4 caractères et sans caractères spéciaux.
On créé une liste des entrées qu'on ajoute et à chaque fois on va vérifier qu'il n'éxiste pas dans notre liste avant de l'ajouter dans le flexTable et on teste le contenu avec un REGEX avec la fonction matches("^[0-9A-Z\\.]{1,10}$")

On affiche un message d'erreur avec l'objet Window, accessible grâce à l'inclusion :
import com.google.gwt.user.client.Window;

On oublie pas d'instancier notre liste stocks ArrayList, juste en dessous des autres déclarations
Puis on écrit notre fonction. Ca donne ça :

On peut enfin ajouter des choses dans notre flexTable ! Enjoy