Mon premier projet GWT - Java Spring Dév . Web Java Android ...

chuckleelephantbutteΛογισμικό & κατασκευή λογ/κού

9 Ιουν 2012 (πριν από 5 χρόνια και 2 μήνες)

496 εμφανίσεις




I-B. Présentation
Au cours de cet article, nous verrons comment utiliser et intégrer le framework GWT avec Eclipse.
La présentation se fera par la réalisation d'une application permettant la consultation et le filtre d'une liste de
contacts.
Les exemples de cet article se feront sous Windows, mais devraient s'adapter à un autre environnement sans
trop de difficultés.
II. Mise en place de l'environnement
II-A. Environnement de développement
Pour commencer, il faut créer le répertoire de base du projet.
On se place dans ce répertoire pour travailler.
Création des fichiers projet Eclipse
Création de l'arborescence applicative
Maintenant que la structure applicative est créée, on pourrait simplement utiliser un éditeur de texte.
Mais utilisons Eclipse, pourquoi se priver de fonctionnalités avancées?
Pour cela, il suffit d'ouvrir Eclipse.
Dans le menu file, choisir import
Choisir Existing Projects into workspace
Cibler le répertoire demoGWT et importer.
On obtient
Création du répertoire
mkdir demoGWT
cd demoGWT
projectCreator -eclipse demoGWT
Created directory D:\gwt-windows-1.1.10\demoGWT\test Created file D:\gwt-windows-1.1.10\demoGWT\.project
Created file D:\gwt-windows-1.1.10\demoGWT\.classpath
applicationCreator -eclipse demoGWT com.developpez.exemple.gwt.client.MonApplication
Created directory D:\gwt-windows-1.1.10\demoGWT\src
Created directory D:\gwt-windows-1.1.10\src\demoGWT\com\developpez\exemple\gwt
Created directory D:\gwt-windows-1.1.10\src\demoGWT\src\com\developpez\exemple\gwt\client
Created directory D:\gwt-windows-1.1.10\src\demoGWT\src\com\developpez\exemple\gwt\public
Created file D:\gwt-windows-1.1.10\src\demoGWT\com\developpez\exemple\gwt\MonApplication.gwt.xml
Created file D:\gwt-windows-1.1.10\src\demoGWT\com\developpez\exemple\gwt\public\MonApplication.html
Created file D:\gwt-windows-1.1.10\src\demoGWT\com\developpez\exemple\gwt\client\MonApplication.java
Created file D:\gwt-windows-1.1.10\demoGWT\MonApplication.launch
Created file D:\gwt-windows-1.1.10\demoGWT\MonApplication-shell.cmd
Created file D:\gwt-windows-1.1.10\demoGWT\MonApplication-compile.cmd


II-B. Environnement de production
En production, on aura évidemment besoin d'un serveur applicatif ou d conteneur web tel Tomcat.
Pour l'installation et le fonctionnement de Tomcat, je vous laisse consulter ce tutoriel.
Ensuite, il vous suffit de déployer votre application comme n'importe quelle autre application Java.

III. Bonjour le monde
Comme tout bon tutoriel, nous allons commencer par un "Hello World !".
Pour cela, lancer le script MonApplication-shell.cmd. Un navigateur va se lancer.
Il vous permettra de voir le rendu de votre application en cours de développement.
La page que vous voyez apparaître devrait ressembler à celle-ci.
Félicitation, vous venez de réussir votre premier "HelloWorld" avec le framework GWT.

IV. On complique un peu
IV-A. Un peu de nettoyage
Le ménage commence par la page HTML qui sert de support à notre application.
On supprime le surplus du HelloWorld pour ne conserver que le titre de la page et les balises propres à GWT.
On obtient alors la page suivante :
MonApplication.html
<head>
<!-- -->
<!-- Ici on défini le titre de notre fenêtre -->
<!-- -->
<title>MonApplication GWT</title>

<!-- -->
<!-- La balise suivante permet de faire le -->
<!-- lien entre la page html et le code GWT -->
<!-- -->
<meta name='gwt:module' content='com.developpez.exemple.gwt.MonApplication'>
</head>

<body>
<!-- -->
<!-- L'inclusion de gwt.js est obligatoire. -->
<!-- Elle placer ici pour des raisons de -->
<!-- preformances. -->
<!-- -->

IV-B. Entrypoint
Lorsque l'on développe une application AWT/SWING, on utilise une classe avec une méthode main pour
lancer notre application.
Etant donné que les classes Java que nous allons écrire seront converties en code Javascript, l'utilisation
d'une méthode main est impossible.
Dans notre cas, notre classe de lancement sera la page html de notre application et notre méthode main la
balise meta.
L'attribut content de la balise permet de faire le lien vers le fichier de configuration de notre module GWT.
La balise entry-point permet de spécifier quelle sera la classe principale de notre application.
Cette classe doit implémenter l'interface Entrypoint.



Il est intéressant aussi d'implémenter l'interface WindowResizeListener.
Cette interface permet de recevoir les informations liées à la taille de la fenêtre du navigateur et donc de
redimensionner notre application proportionnellement à celle-ci.
Le code de la classe devrait ressembler à ça:
<script language="javascript" src="gwt.js"></script>

<!-- La balise suivante est optionnelle, elle gère l'historique des pages -->
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
</body>
</html>
Déclaration du module
<meta name='gwt:module' content='com.developpez.exemple.gwt.MonApplication'>
MonApplication.gwt.xml
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.developpez.exemple.gwt.client.MonApplication'/> </module>
MonApplication.java
package com.developpez.exemple.gwt.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener; /**
* Entry point classes define <code>onModuleLoad()</code>. */
public class MonApplication implements EntryPoint , WindowResizeListener {
On obtient donc une application GWT pleinement fonctionnelle, mais qui ne fait rien.

IV-C. Création des éléments graphiques
Les classes des éléments graphiques de GWT reprennent les noms et comportements que l'on a l'habitude de
manipuler quand on réalise une application AWT/SWING. Avec GWT, nous manipulerons donc des Panels et
autres Label et TextBox.
IV-C-1. Les Panels
Les panels se déclinent en plusieurs classes qui ont chacune un comportement spécifique.



Dans cette mise en application nous utiliserons les panels suivants :

￿ DockPanel
￿ HorizontalPanel
￿ VerticalPanel
Le DockPanel servira de base d'accueil pour notre application. Il contiendra dans sa partie Nord un
VerticalPanel et dans sa partie Centre un HorizontalPanel.
Le verticalPanel contiendra les champs de recherche et le VerticalPanel présentera les résultats.

On commence par ajouter le DockPanel à l'application. Ce qui nous donne pour la classe MonApplication.java
le code suivant :
/**
* This is the entry point method. */ public void onModuleLoad() {
// Hook the window resize event, so that we can adjust the UI.
Window.addWindowResizeListener(this);
// Get rid of scrollbars, and clear out the window's built-in margin,
// because we want to take advantage of the entire client area.
Window.enableScrolling(false); Window.setMargin("10px"); } public void onWindowResized(int width, int height) {
// TODO Auto-generated method stub
} }
MonApplication.java
package com.developpez.exemple.gwt.client;

Nous allons créer deux panels, RechechePanel et ContactsPanel qui étendent respectivement HorizontalPanel
et VerticalPanel.
Le fait de ne pas utiliser directement les panels génériques nous permet d'alléger la classe MonApplication et
surtout nous permettra d'avoir un code lisible.
Pour la classe ContactsPanel et pour la classe RecherchePanel
Il ne nous reste plus qu'à les insérer dans le DockPanel.
import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener; import com.google.gwt.user.client.ui.DockPanel; import com.google.gwt.user.client.ui.RootPanel; /**
* Entry point classes define <code>onModuleLoad()</code>. */
public class MonApplication implements EntryPoint , WindowResizeListener {
private DockPanel outer = new DockPanel();
/**
* This is the entry point method. */ public void onModuleLoad() {

outer.setWidth("100%");
outer.setHeight("100%");
// Hook the window resize event, so that we can adjust the UI.
Window.addWindowResizeListener(this);
// Get rid of scrollbars, and clear out the window's built-in margin,
// because we want to take advantage of the entire client area.
Window.enableScrolling(false); Window.setMargin("10px");
RootPanel.get().add(outer); } public void onWindowResized(int width, int height) {
// TODO Auto-generated method stub
} }
MonApplication.java
package com.developpez.exemple.gwt.client;
import com.developpez.exemple.gwt.client.panel.ContactsPanel;
import com.developpez.exemple.gwt.client.panel.RecherchePanel; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener; import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.RootPanel; /**
* Entry point classes define <code>onModuleLoad()</code>. */
public class MonApplication implements EntryPoint , WindowResizeListener {
private DockPanel outer = new DockPanel();
/**
* This is the entry point method. */ public void onModuleLoad() {
HorizontalPanel recherchePanel =new RecherchePanel();
VerticalPanel contactsPanel =new ContactsPanel();

outer.setWidth("100%");
outer.setHeight("100%");

IV-C-2. Les éléments graphiques
Maintenant que la structure d'accueil de notre application est prête, nous allons pouvoir mettre un peu de
contenu.
En plus des composants graphiques de base, nous utiliserons aussi la classe Composite.
La classe Composite permet d'envelopper un ou plusieurs autres éléments graphiques. Ce groupe de
composant agit alors comme un seul et même élément.
Nous allons commencer par créer une classe Texte que héritera de Composite. Cette classe nous permettra
de gérer les zones de saisie utilisateur.
Elle gèrera le libellé et la zone de saisie. on utilisera la classe Label pour le libélé et la classe TextBox pour la
zone de saisie.


// Hook the window resize event, so that we can adjust the UI.
Window.addWindowResizeListener(this);
// Get rid of scrollbars, and clear out the window's built-in margin,
// because we want to take advantage of the entire client area.
Window.enableScrolling(false); Window.setMargin("10px");
outer.add(recherchePanel, DockPanel.NORTH);
outer.add(contactsPanel, DockPanel.CENTER);
RootPanel.get().add(outer); } public void onWindowResized(int width, int height) {
// TODO Auto-generated method stub
} }
Texte.java
package com.developpez.exemple.gwt.client.panel; import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; public class Texte extends Composite {
private Label label = new Label();
private TextBox textBox = new TextBox();

public Texte() {
HorizontalPanel panel =new HorizontalPanel();
panel.add(label);
panel.add(textBox);
initWidget(panel);
}

public void setLabel(String texte){
label.setText(texte+" : ");
}
public void setTexte(String texte){
textBox.setText(texte);
}

public String getTexte(){
return textBox.getText();
Ensuite, il suffit d'ajouter ce composant à notre RecherchePanel, pour avoir nos zones de filtre.
Avant de compléter notre application, nous allons créer une classe utilitaire Contact.
Ce sera la représentation objet des différentes personnes de notre application.
Afin d'avoir quelques éléments graphiques pour la démonstration, on rajoute une méthode getAllContacts()
sur la classe.
Cette méthode va nous renvoyer un tableau de contacts à afficher, le temps que l'on implémente le service
d'accès à une base de données.
A terme cette méthode disparaîtra.


Les différents contacts connus seront affichés sous forme de tableau.
Nous utiliserons pour cela la classe FlexTable. Le contenu d'un tableau se positionne par ses coordonées.
Nous utiliserons la première ligne pour afficher les entêtes de tableau.
} }
RecherchePanel.java
package com.developpez.exemple.gwt.client.panel; import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel; public class RecherchePanel extends HorizontalPanel {
public RecherchePanel(){
this.setTitle("Recherche");
this.setWidth("100%");
Texte tb = new Texte();
tb.setLabel("Nom");
add(tb);

Texte tb2 = new Texte();
tb2.setLabel("Prénom");
add(tb2);
} }
ContactsPanel.java
package com.developpez.exemple.gwt.client.panel;
import com.developpez.exemple.gwt.client.util.Contact; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.VerticalPanel; public class ContactsPanel extends VerticalPanel {
Une fois compilée, notre application donne ça.
IV-D. Utilisation des styles css
Maintenant que l'on a tous nos éléments, on va leur donner un aspect un peu plus convivial.
Pour cela, on va utiliser un fichier css.
On ajoute donc un fichier MonApplication.css au répertoire public de notre arborescence.
Afin que ces styles soient disponibles dans les classes GWT, il faut éditer le fichier MonApplication.gwt.xml, et
déclarer le fichier css dans notre module.
Pour cela il suffit d'ajouter la ligne suivante dans la déclaration du module.
Les différentes classes graphiques du framework GWT héritent toutes de la classe UIObject.


private FlexTable t = new FlexTable();

public ContactsPanel() {

t.setTitle("Contacts");
t.setText(0, 0,"Nom");
t.setText(0, 1,"Prénom");
t.setText(0, 2,"Email");
t.setText(0, 3,"Tel");
t.setWidth("100%");
t.setCellSpacing(2);

for (int i = 0; i < Contact.getAllContacts().length; ++i)
addContact(Contact.getAllContacts()[i],i+1);

this.add(t);
this.setWidth("100%");
}
private void addContact(Contact contact,int i) {
t.setText(i, 0,contact.getNom());
t.setText(i, 1,contact.getPrenom());
t.setText(i, 2,contact.getEmail());
t.setText(i, 3,contact.getTel());
}
}
MonApplication.gwt.xml
<stylesheet src='MonApplication.css'/>


Cette classe nous donne la méthode setStyleName sur tous nos composants et nous permet donc d'assigner
un style précis à chacun de nos objets.
Par exemple, pour changer le style du RecherchePanel, il nous suffit d'ajouter le code suivant à son
constructeur pour en modifier l'apparence.
Bien évidemment le style gwt-RecherchePanel a été défini dans le fichier css.
Par convention, les noms de style sont composés du nom du module tiret l'élément grahique auquel il
s'applique.
En appliquant nos styles à nos différents éléments, on obtient ça.
Mais bien sûr, nous n'avons encore aucun composant actif dans notre page.

V. Activation du filtre
Nous allons commencer à mettre un peu d'intelligence dans notre application. Pour cela, nous allons écouter
les événements sur les zones de saisie et modifier le contenu du tableau en conséquence.
On va commencer par se donner des accesseurs à nos Panels en leur appliquant le pattern Singleton. Puis on
va rajouter les méthodes getNom et getPrenom sur le RecherchePanel et la méthode filtre sur le
contactsPanel.
Les méthodes getNom et getPrenom retourneront les valeurs saisies tandis que filtre modifiera le contenu du
tableau de résultats. Ensuite, on va écouter les événements clavier qui surviennent dans nos zones de saisie
en ajoutant le code suivant à notre classe Texte.
this.setStyleName("gwt-RecherchePanel");
Texte.java
textBox.addKeyboardListener(new KeyboardListener() {
public void onKeyDown(Widget sender, char keyCode, int modifiers) {}
public void onKeyPress(Widget sender, char keyCode, int modifiers) {}
public void onKeyUp(Widget sender, char keyCode, int modifiers) {
ContactsPanel.instance.filtre();
}
});
On remplit la méthode filtre.
Une fois nos classes modifiées, on obtient ça.
VI. Dialogue avec le serveur
L'application semble fonctionnelle, mais la liste des contacts reste encore contenue dans la classe Contact, ce
qui est peu satisfaisant.
Nous allons donc dans un premier temps créer un package server qui recevra les classes distantes et
supprimer la méthode static getAllContact de la classe Contact.

VI-A. Mise en place d'un service
Le framework GWT dispose de sa propre solution de communication entre le client et le serveur, basée sur le
principe d'appel de procédure distante (RCP).
Le serveur et le client dialogue dialoguent en Asynchrone (vous savez le premier A de AJAX ).
Il faut donc deux flux de communication, le premier direct vers le serveur pour émettre les requêtes, le
second asynchrone pour recevoir les réponses du serveur.
Le flux ascendant est modélisé par une interface qui doit étendre l'interface RemoteService.
On définit dessus les différentes méthodes que l'on souhaite obtenir du serveur.
On va donc créer une interface ContactService.


Afin que le client puisse recevoir la réponse du serveur, on va créer une seconde interface
ContactServiceAsync.
Cette interface doit répondre à plusieurs critères :

￿ Le nom de l'interface doit être le même que celui pour le flux ascendant avec à la fin "Async".
￿ Toutes ses méthodes sont de type void.
￿ Le nombre et le nom de ses méthodes sont identiques à ceux pour le flux ascendant.
￿ Chacune de ses méthodes doit prendre les mêmes paramètres que pour le flux montant plus un
paramètre supplémentaire de la classe AsyncCallback.
ContactsPanel.java
public void filtre(){
String nom = RecherchePanel.instance.getNom();
String prenom = RecherchePanel.instance.getPrenom();
for (int i = t.getRowCount()-1; i >0 ; i--) {
t.removeRow(1);
}
int next =1;
for (int i = 0; i < Contact.getAllContacts().length; ++i){
Contact contact =Contact.getAllContacts()[i];

if (contact.getNom().toUpperCase().startsWith(nom.toUpperCase())
&& contact.getPrenom().toUpperCase().startsWith(prenom.toUpperCase())) {
addContact(contact,next);
next++;
} } }
C'est au travers de l'objet AsyncCallback que le serveur retournera sa réponse au client.



Maintenant que nous avons nos flux de communication avec le serveur, il nous faut ensuite créer une servlet
sur le serveur capable de recevoir notre demande et d'y répondre.
Pour cela dans le package server, on va créer une classe ContactServiceImpl qui étendra
RemoteServiceServlet et impémentera notre interface ContactService.
Hériter de la classe RemoteServiceServlet permet de faire abstraction de l'élaboration de l'objet
AsyncCallback.
Le mécanisme RCP fonctionne comme un miroir, les méthodes appelées coté client seront exécutées coté
serveur sur notre servlet.
C'est donc dans le corps des méthodes issues de l'implémentation de notre interface que l'on placera le code
que l'on souhaite exécuter sur le serveur.
Notre classe servlet elle aussi doit répondre à plusieurs critères :

￿ Le nom de la servlet doit être le même que celui pour le flux ascendant avec à la fin "Impl".
￿ La servlet doit implémenter RemoteServiceServlet.
￿ La servlet doit implémenter l'interface du service ascendant.

La classe ContactData est une classe utilitaire chargée de fournir la liste des contacts.
La méthode d'obtention des contacts importe peu, jdbc, Hibernate, fichier XML, LDAP, libre à vous d'utiliser
celle qu'il vous plait.
Dernière action pour finaliser la création de notre service, la déclaration dans le fichier
MonApplication.gwt.xml.
Pour cela, il suffit d'ajouter la ligne suivante à la déclaration du module.
ContactServiceImpl.java
package com.developpez.exemple.gwt.server;
import com.developpez.exemple.gwt.client.ContactService;
import com.developpez.exemple.gwt.client.util.Contact;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class ContactServiceImpl extends RemoteServiceServlet implements
ContactService {
public Contact[] getAllContact() {
return ContactData.getAllContacts();
} }

VI-B. Exploitation du service
Maintenant que le service est créé, nous allons pouvoir l'utiliser. On va l'appeler directement dans notre
classe ContactsPanel.
On rajoute une méthode getAllContacts sur notre classe, qui après quelques modifications ressemble à ça :
MonApplication.gwt.xml
<servlet path="/contactService" class="com.developpez.exemple.gwt.server.ContactServiceImpl"/>
ContactsPanel.java
package com.developpez.exemple.gwt.client.panel;
import com.developpez.exemple.gwt.client.ContactService;
import com.developpez.exemple.gwt.client.ContactServiceAsync;
import com.developpez.exemple.gwt.client.util.Contact;
import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.VerticalPanel; public class ContactsPanel extends VerticalPanel {
private FlexTable t = new FlexTable();
private Contact[] contacts;

public static ContactsPanel instance;
public ContactsPanel() {
getAllContacts();
t.setTitle("Contacts");
t.setText(0, 0,"Nom");
t.setText(0, 1,"Prénom");
t.setText(0, 2,"Email");
t.setText(0, 3,"Tel");
t.setWidth("100%");
t.setCellSpacing(2);

for (int i = 0; i < 4; i++) {
t.getCellFormatter().addStyleName(0, i, "contact-ContactPanel");
}
this.add(t);
this.setWidth("100%");
instance=this;
}
private void addContact(Contact contact,int i) {
t.setText(i, 0,contact.getNom());
t.setText(i, 1,contact.getPrenom());
t.setText(i, 2,contact.getEmail());
t.setText(i, 3,contact.getTel());

for (int j = 0; j < 4; j++) {
if(i%2==0)
t.getCellFormatter().addStyleName(i, j, "contact-ContactPanel-line1");
else
t.getCellFormatter().addStyleName(i, j, "contact-ContactPanel-line2");
}
}

public void filtre(){
String nom = RecherchePanel.instance.getNom();
String prenom = RecherchePanel.instance.getPrenom();
for (int i = t.getRowCount()-1; i >0 ; i--) {
t.removeRow(1);
}
int next =1;
for (int i = 0; i < contacts.length; ++i){
Contact contact =contacts[i];

if (contact.getNom().toUpperCase().startsWith(nom.toUpperCase())

&& contact.getPrenom().toUpperCase().startsWith(prenom.toUpperCase())) {
addContact(contact,next);
next++;
}
}
Si on détaille un peu la méthode getAllContacts() :
J'ai utilisé une classe interne car le comportement voulu était très simple, mais dans un cadre plus complexe,
il serait souhaitable d'utiliser une classe externe.
Dans notre exemple la mise place et l'appel du service sont fait dans la même méthode car l'appel du service
n'est fait qu'une seule fois au chargement de la page.
Néanmoins, on peut très bien placer notre service sur un slot et y faire ensuite appel en différente occasion.
Chaque appel à un service génère un aller retour serveur. Il faut donc prévoir les temps de latence possible.
De plus il est intéressant comme dans notre application, de stocker en cache côté client un certain nombre
d'information, afin d'alléger le nombre de requète au serveur.
Typiquement dans notre exemple, il était inutile de faire un aller/retour serveur pour le filtre (à la volumétrie
près).
Notre application est maintenant terminée et nous obtenons la liste des contacts d'un serveur distant.

VII. Déploiement sur Tomcat
}

private void getAllContacts(){
contacts = new Contact[0];
// define the service you want to call
ContactServiceAsync svc =
(ContactServiceAsync) GWT.create(ContactService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) svc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "contactService";
endpoint.setServiceEntryPoint(moduleRelativeURL);

AsyncCallback callback = new AsyncCallback() {
public void onSuccess (Object result)
{
contacts = (Contact[]) result;
filtre();
}
public void onFailure (Throwable ex)
{
contacts = new Contact[0];
filtre();
}
};

// execute the service
svc.getAllContact(callback);
} }
Déclaration du service que l'on souhaite appeler
ContactServiceAsync svc = (ContactServiceAsync) GWT.create(ContactService.class);
On définit ou trouver le service, son url
ServiceDefTarget endpoint = (ServiceDefTarget) svc;
String moduleRelativeURL = GWT.getModuleBaseURL() + "contactService";
endpoint.setServiceEntryPoint(moduleRelativeURL);
On définit le comportement de retour
AsyncCallback callback = new AsyncCallback() {
public void onSuccess (Object result)
{
contacts = (Contact[]) result;
filtre();
}
public void onFailure (Throwable ex)
{
contacts = new Contact[0];
filtre();
}
};
on appelle le service
svc.getAllContact(callback);

VIII. Conclusion
Au cours de cet article, nous avons vu tout l'intérêt du framework GWT.
Nous avons réalisé une application web interactive, dialoguant avec un serveur, en faisant abstraction de tout
autre language à part Java.
De plus le code généré est compatible avec la majorité des navigateurs.
Le framework GWT apporte au développement WEB tous les avantages du développement d'un client lourd,
en permettant notamment la modélisation des classes gérant l'interface graphique.

IX. Sources
Fichiers sources de la première partie du tutoriel ici ou ici.
Fichiers sources du chapitre VI ici ou ici.
phpMyVisites | Open source web analytics
Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par
quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
Vos questions techniques : forum d'entraide Dév. Web Java -
Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Hébergement - Participez - Copyright © 2000-2010 www.developpez.com - Legal informations.