SlideShare une entreprise Scribd logo
1  sur  17
Télécharger pour lire hors ligne
Atelier
Objectif
Création une application basic avec GWT pour familiarise avec le Framework
                                  Description
Dans ce TP on vas crée une application StockWatcher les principes
fonctionnements de l’application sont :

    Permet aux utilisateurs la possibilité d'ajouter des actions
    Afficher les informations suivantes pour chaque stock: symbole, le cours,
     le changement depuis le dernier rafraîchissement
    Fournir aux utilisateurs la possibilité de supprimer un support dans la liste
     Actualiser le prix des actions

    Calculer la variation depuis la dernière actualisation à la fois comme un
     nombre et un pourcentage
    Afficher un horodatage indiquant la dernière mise à jour
Les éléments d'interface utilisateur:
 une table pour contenir les données de stock
 deux boutons, l'un pour ajouter des actions et un pour les supprimer
 une zone de saisie pour entrer le code de stock
 un timestamp pour afficher l'heure et la date de la dernière actualisation



                 Les étapes de créations de l’application
   Creation d’un nouveau projet
   création d’interface utilisateur
   manager les événements
   debug l’application
   application d’un style (css)
   complies l’application
   client-serveur communication (RPC)


                          Ajout du plugin mojo
Création du projet GWT avec Maven
Client serveur communication RPC
  Principe de fonctionnement

                                                                        Code GWT


On demande un service mais
on n’attend pas la réponse                                         Interface asynchrone
Celle-ci viendra en son
temps grâce à un « objet de
rappel ».
                                                                   Interface synchrone




                                                                      Code Serveur


  Créer un service
   Coté client, définir une interface dite synchrone qui étend RemoteService et qui liste
    toutes les méthodes RPC
   Coté serveur, implémenter l’interface et étendre RemoteServiceServlet
   Coté client, définir une interface asynchrone basée sur la première interface avec le
    même nombre de méthodes que la première interface
Interface synchrone coté client
               Spécification de vos services

Import com.google.gwt.user.client.rpc.RemoteService;
public interface MyService extends RemoteService {

public T myMethod(T1 p1, T2 p2, T3 p3);

          }

        Implémentation coté serveur
            Implémentation de vos services

public class MyServiceImpl extends RemoteServiceServlet
implements MyService {
public T myMethod(T1 p1, T2 p2, T2 p3) {
              // …
              return r;
      }
}

  Interface asynchrone coté client
         Implémentation de vos services

interface MyServiceAsync {

public void myMethod(T1 p1, T2 p2,T2 p3,
AsyncCallback<T> callback);

    }
Appel de méthodes asynchrones
   o Un appel de méthode asynchrone nécessite de passer un objet de
     rappel (callback object)
   o L’objet de rappel est notifié lorsque l’appel asynchrone est
     terminé
   o En attendant l’appelant continu son activité
   o Remarquez que les méthodes asynchrones ont un type résultat
     void
   o Conventions de nommage
   o Nom des classes et interfaces
     – MyService interface synchrone
     – MyServiceImpl implementation
     – MyServiceAsync interface asynchrone

   o Chaque méthode dans l’interface synchrone doit avoir une
     méthode correspondante dans l’interface asynchrone avec un
     paramêtre extra en dernier argument de type AsyncCallback

  o Méthode de l’interface synchrone
public Integer[ ] myMethod(String s, int i)

  o Méthode de l’interface asynchrone
public void myMethod(String s,int i, AsyncCallback<Integer[ ]>
    callback)


         Utilisation de services
• Créer une instance de service
MonServiceAsync monService = GWT.create(MonService.class);


• Appel de méthode à distance
monService.maMethode(p1,p2, new AsyncCallBack<T>() {
   public onFailure(Trowable t) {...}
   public onSuccess(T result) {...}
})


Chemin d’accès à un service
• Le chemin d’accès à un service est composé de deux parties
– /nomDuModule/nomDuService
• Le nom du service peut être défini de deux manières
– Statiquement par annotation dans l’interface synchrone
@RemoteServiceRelativePath("service")

– Dynamiquement
ServiceAsync service = GWT.create(Service.class);
ServiceDefTarget test = (ServiceDefTarget) service
test.setServiceEntryPoint("/module/service");

• Les déclarations de path pour la servlet doivent être cohérentes
– Dans le descripteur de module
<servlet class= "MaServlet" path="/module/service"/>

– Dans le descripteur web.xml
<url-pattern>/module/service</urlpattern>
                                   Application
Dans ce mini tutorial nous allons creer une petite application qui implémente le
service propose par le framework GWT .Ceer un nouveau projet et suivre les
diffférentes etapes decritent .

I Configuration

Afin de définir et configurer une interface RPC asynchrone, vous aurez besoin
de créer trois nouveaux fichiers:

1. MonService

Une interface implémentant RemoteService dans laquelle vous définirez les
méthodes que vous voudrez appeler. Vous définirez grâce à
l’annotation @RemoteServiceRelativePath(String path), le chemin grâce auquel
vous accéderez à votre service:Cette classe doit etre créée dans le package client

1 //MonService.java

2 @RemoteServiceRelativePath("monservice")
3 public interface MonService extends RemoteService {

4     String exempleMethode();

5}


      Toutes vos méthodes asynchrones doivent avoir un retour de
type Serializable !

2. MonServiceImpl

Une classe située dans le package server, étendant RemoteServiceServlet et
implémentant MonService, dont vous implémenterez les méthodes :

1 //MonServiceImpl.java

    public class MonServiceImpl extends RemoteServiceServlet implements Mon
2
    Service {

3

4     @Override

5     public String exempleMethode() {

6         return "Réponse du Serveur";

7     }

8

9}

3. MonServiceAsync

Une interface devant être dans le même package que MonService et dont le nom
devra être le même que celle-ci suivi de Async (e.g :MonServiceAsync). Dans
cette interface, vous définirez les mêmes méthodes que dans MonService, mis a
part quelques détails:
1 //MonServiceAsync.java

2 public interface MonServiceAsync {

3

4     void exempleMethode(AsyncCallback<String> callback);

5

6}


Comme vous pouvez le voir, la méthode dans cette interface retourne void, donc
rien. En effet, toutes vos méthodes dans cette interface auront un type de
retour void. Cependant, le type de retour de vos méthodes définies
dans MonService se retrouvent dans l’argument supplémentaire de votre
méthode : AsyncCallback<String> callback. Toutes vos méthodes
définies dans MonService devront donc être ainsi transposées
dansMonServiceAsync.

Maintenant, afin de pouvoir accéder à notre code côté serveur, nous allons avoir
besoin de configurer une servlet qui contiendra l’implémentation
de MonService dans le web.xml. Rien de différent ici avec la définition
habituelle des servlets en Java. Vous préciserez donc la classe de la servlet, ainsi
que son chemin (celui définit dans MonService).


     <!--MonServiceAsync.java-->
01

02 <servlet>

0
       <servlet-name>monServiceImpl</servlet-name>
3

     <servlet-
0
  class>com.gwtfrance.mapremiereapplication.server.MonServiceImpl</servlet
4
  -class>

05 </servlet>
06

07 <servlet-mapping>

08   <servlet-name>monServiceImpl</servlet-name>

09   <url-pattern>/ma_premiere_application/monservice</url-pattern>

10 </servlet-mapping>


Voilà, votre application est prête à utiliser les appels asynchrones. Si vous le
désirez, maintenant que vous savez à quoi servent les
fichiersGreetingService, GreetingServiceAsync, et GreetingServiceImpl, vous
pouvez les supprimer, ainsi que la configuration de la
servlet greetingServicedans le web.xml.

II. Utilisation

GWT-RPC étant configuré, nous allons pouvoir effectuer nos appels
asynchrones. Pour ceci, vous aurez besoin de créer une instance du proxy de
service :Créer une classe dans le package client qui implément le
entryPoint :explement :Ma_Premiere_Application.java

1 //Ma_Premiere_Application.java

2 final MonServiceAsync monService = GWT.create(MonService.class);


Je vous conseille fortement de faire de cette instance un Singleton, étant inutile
de réinstancier systématiquement ce proxy.

Afin de pouvoir gérer les retour de notre appel asynchrone, nous aurons besoin
d’un objet AsyncCallback.

01 //Ma_Premiere_Application.java

02 final AsyncCallback<String> callback = new AsyncCallback<String>() {



04         @Override
05           public void onFailure(Throwable caught) {

    06               Window.alert("Erreur lors de l'appel serveur");

    07

    08           }

    09

    10           @Override

    11           public void onSuccess(String result) {

    12               Window.alert(result);

    13

    14           }

    15      };


    Comme vous pouvez le voir, lors de l’instanciation de notre objet callback, nous
    devons implémenter deux méthode:

   La méthode onFailure(Throwable caught) est appelée lorsque une erreur se
    produit côté serveur lors de votre appel. Grâce à l’objetThrowable, vous pourrez
    récupérer les exceptions lancées côté serveur et les traiter comme vous
    l’entendez.
   La méthode onSuccess(String result) est elle appelée lorsque le traitement
    serveur s’est passé sans problème. L’objet retourné correspond à l’objet retourné
    par votre implémentation côté serveur.

    Notre objet callback étant maintenant défini, nous pouvons donc effectuer notre
    appel asynchrone. Ici, nous remplaçons le code de la méthodeonClick(Event
    event) par notre appel:

    1 //Ma_Premiere_Application.java

    2 monBouton.addClickHandler(new ClickHandler() {
3

4           @Override

5           public void onClick(ClickEvent event) {

6               monService.exempleMethode(callback);

7

8           }

9        });


StockWatcher.java



package com.google.gwt.sample.stockwatcher.client;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class StockWatcher implements EntryPoint {

 private VerticalPanel mainPanel = new VerticalPanel();
 private FlexTable stocksFlexTable = new FlexTable();
 private HorizontalPanel addPanel = new HorizontalPanel();
 private TextBox newSymbolTextBox = new TextBox();
 private Button addStockButton = new Button("Add");
 private Label lastUpdatedLabel = new Label();
 private ArrayList<String> stocks = new ArrayList<String>();
 private static final int REFRESH_INTERVAL = 5000; // ms
/**
  * Entry point method.
  */
 public void onModuleLoad() {
   // Create table for stock data.
   stocksFlexTable.setText(0, 0, "Symbol");
   stocksFlexTable.setText(0, 1, "Price");
   stocksFlexTable.setText(0, 2, "Change");
   stocksFlexTable.setText(0, 3, "Remove");
// Add styles to elements in the stock list table.
   stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader");
   stocksFlexTable.addStyleName("watchList");
   stocksFlexTable.getCellFormatter().addStyleName(0, 1, "watchListNumericColumn");
   stocksFlexTable.getCellFormatter().addStyleName(0, 2, "watchListNumericColumn");
   stocksFlexTable.getCellFormatter().addStyleName(0, 3, "watchListRemoveColumn");
   // Assemble Add Stock panel.
   addPanel.add(newSymbolTextBox);
   addPanel.add(addStockButton);
   addPanel.addStyleName("addPanel");
   // Assemble Main panel.
   mainPanel.add(stocksFlexTable);
   mainPanel.add(addPanel);
   mainPanel.add(lastUpdatedLabel);

    // Associate the Main panel with the HTML host page.
    RootPanel.get("stockList").add(mainPanel);

    // Move cursor focus to the input box.
    newSymbolTextBox.setFocus(true);


   // Setup timer to refresh list automatically.
   Timer refreshTimer = new Timer() {
     @Override
     public void run() {
       refreshWatchList();
     }
   };
   refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
//Listen for mouse events on the Add button.
   newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
           public void onKeyPress(KeyPressEvent event) {
              // if (event.getCharCode() == KeyCodes.KEY_ENTER) {
                  addStock();
               // }
       }
     });

}

/**
 * Add stock to FlexTable. Executed when the user clicks the addStockButton or
 * presses enter in the newSymbolTextBox.
 */
  private void addStock() {
            final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
            newSymbolTextBox.setFocus(true);

            // Stock code must be between 1 and 10 chars that are numbers, letters, or dots.
            if (!symbol.matches("^[0-9A-Z.]{1,10}$")) {
Window.alert("'" + symbol + "' is not a valid symbol.");
              newSymbolTextBox.selectAll();
              return;
          }

          newSymbolTextBox.setText("");

          // Don't add the stock if it's already in the table.
          if (stocks.contains(symbol))
            return;

        // Add the stock to the table.
           int row = stocksFlexTable.getRowCount();
           stocks.add(symbol);
           stocksFlexTable.setText(row, 0, symbol);
           stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn");
           stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn");
           stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn");
        // Add a button to remove this stock from the table.
           Button removeStockButton = new Button("x");
           removeStockButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent event) {
               int removedIndex = stocks.indexOf(symbol);
               stocks.remove(removedIndex);       stocksFlexTable.removeRow(removedIndex + 1);
             }
           });
           stocksFlexTable.setWidget(row, 3, removeStockButton);

        // Get the stock price.
           refreshWatchList();
         }
/**
 * Update a single row in the stock table.
 *
 * @param price Stock data for a single row.
 */
private void updateTable(StockPrice price) {
  // Make sure the stock is still in the stock table.
  if (!stocks.contains(price.getSymbol())) {
    return;
  }

 int row = stocks.indexOf(price.getSymbol()) + 1;

 // Format the data in the Price and Change fields.
 String priceText = NumberFormat.getFormat("#,##0.00").format(
    price.getPrice());
 NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00");
 String changeText = changeFormat.format(price.getChange());
 String changePercentText = changeFormat.format(price.getChangePercent());

 // Populate the Price and Change fields with new data.
 stocksFlexTable.setText(row, 1, priceText);
 stocksFlexTable.setText(row, 2, changeText + " (" + changePercentText
    + "%)");
}
private void refreshWatchList() {
         final double MAX_PRICE = 100.0; // $100.00
           final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
StockPrice[] prices = new StockPrice[stocks.size()];
          for (int i = 0; i < stocks.size(); i++) {
           double price = Random.nextDouble() * MAX_PRICE;
           double change = price * MAX_PRICE_CHANGE
               * (Random.nextDouble() * 2.0 - 1.0);

              prices[i] = new StockPrice(stocks.get(i), price, change);
          }

            updateTable(prices);
          }
 private void updateTable(StockPrice[] prices) {

         for (int i = 0; i < prices.length; i++) {
             updateTable(prices[i]);
         }
       // Display timestamp showing last refresh.
           lastUpdatedLabel.setText("Last update : "
              + DateTimeFormat.getMediumDateTimeFormat().format(new Date()));
  }
}
StockWatcher.css

/* Formatting specific to the StockWatcher application */

body {
  padding: 10px;
}

/* stock list header row */
.watchListHeader {
  background-color: #2062B8;
  color: white;
  font-style: italic;
}

/* stock list flex table */
.watchList {
  border: 1px solid silver;
  padding: 2px;
  margin-bottom:6px;
}

/* stock list Price and Change fields */
.watchListNumericColumn {
  text-align: right;
  width:8em;
}

/* stock list Remove column */
.watchListRemoveColumn {
  text-align: center;
}

/* Add Stock panel */
.addPanel {
  margin: 10px 0px 15px 0px;
}
Atelier gwt

Contenu connexe

Tendances

Android-Tp5 : web services
Android-Tp5 : web servicesAndroid-Tp5 : web services
Android-Tp5 : web servicesLilia Sfaxi
 
Python avancé : Interface graphique et programmation évènementielle
Python avancé : Interface graphique et programmation évènementiellePython avancé : Interface graphique et programmation évènementielle
Python avancé : Interface graphique et programmation évènementielleECAM Brussels Engineering School
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationECAM Brussels Engineering School
 
Cours 2 les architectures reparties
Cours 2 les architectures repartiesCours 2 les architectures reparties
Cours 2 les architectures repartiesMariem ZAOUALI
 
Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbcabderrahim marzouk
 
Real Time Meta Events
Real Time Meta EventsReal Time Meta Events
Real Time Meta Eventskerush
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database ConnectivityKorteby Farouk
 
VIM puissance PHP = VI Improved !
VIM puissance PHP = VI Improved !VIM puissance PHP = VI Improved !
VIM puissance PHP = VI Improved !Frederic Hardy
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateursAziz Darouichi
 
Python avancé : Ensemble, dictionnaire et base de données
Python avancé : Ensemble, dictionnaire et base de donnéesPython avancé : Ensemble, dictionnaire et base de données
Python avancé : Ensemble, dictionnaire et base de donnéesECAM Brussels Engineering School
 

Tendances (20)

Android-Tp5 : web services
Android-Tp5 : web servicesAndroid-Tp5 : web services
Android-Tp5 : web services
 
Python avancé : Interface graphique et programmation évènementielle
Python avancé : Interface graphique et programmation évènementiellePython avancé : Interface graphique et programmation évènementielle
Python avancé : Interface graphique et programmation évènementielle
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulation
 
Cours 2 les architectures reparties
Cours 2 les architectures repartiesCours 2 les architectures reparties
Cours 2 les architectures reparties
 
Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbc
 
Johnny-Five : Robotique et IoT en JavaScript
Johnny-Five : Robotique et IoT en JavaScriptJohnny-Five : Robotique et IoT en JavaScript
Johnny-Five : Robotique et IoT en JavaScript
 
Le Réseau et Java
Le Réseau et JavaLe Réseau et Java
Le Réseau et Java
 
Sockets
SocketsSockets
Sockets
 
Php seance1
Php seance1Php seance1
Php seance1
 
Développement informatique : Programmation graphique
Développement informatique : Programmation graphiqueDéveloppement informatique : Programmation graphique
Développement informatique : Programmation graphique
 
Real Time Meta Events
Real Time Meta EventsReal Time Meta Events
Real Time Meta Events
 
Cours javascript v1
Cours javascript v1Cours javascript v1
Cours javascript v1
 
Java Database Connectivity
Java Database ConnectivityJava Database Connectivity
Java Database Connectivity
 
PHP mysql Xml.pdf
PHP mysql Xml.pdfPHP mysql Xml.pdf
PHP mysql Xml.pdf
 
Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)
 
VIM puissance PHP = VI Improved !
VIM puissance PHP = VI Improved !VIM puissance PHP = VI Improved !
VIM puissance PHP = VI Improved !
 
Héritage et redéfinition de méthode
Héritage et redéfinition de méthodeHéritage et redéfinition de méthode
Héritage et redéfinition de méthode
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateurs
 
Python avancé : Qualité de code et convention de codage
Python avancé : Qualité de code et convention de codagePython avancé : Qualité de code et convention de codage
Python avancé : Qualité de code et convention de codage
 
Python avancé : Ensemble, dictionnaire et base de données
Python avancé : Ensemble, dictionnaire et base de donnéesPython avancé : Ensemble, dictionnaire et base de données
Python avancé : Ensemble, dictionnaire et base de données
 

En vedette

Université : pour une nouvelle ambition
Université : pour une nouvelle ambition Université : pour une nouvelle ambition
Université : pour une nouvelle ambition Hortense Billot
 
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0Hicham Sabre
 
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !Yann Costaz
 
L'histoire de Lyon
L'histoire de Lyon L'histoire de Lyon
L'histoire de Lyon albii_9
 
Présentation Mind Fruits, L'agence qui digitalise votre Marketing
Présentation Mind Fruits, L'agence qui digitalise votre MarketingPrésentation Mind Fruits, L'agence qui digitalise votre Marketing
Présentation Mind Fruits, L'agence qui digitalise votre MarketingGuillaume Eouzan
 
-Stage metayer morgane
-Stage metayer morgane-Stage metayer morgane
-Stage metayer morganemorgane2
 
choix des prothèses aortiques cardiaques
choix des prothèses aortiques cardiaqueschoix des prothèses aortiques cardiaques
choix des prothèses aortiques cardiaquesSlim Chenik
 
C’est masculine ou féminin
C’est masculine ou fémininC’est masculine ou féminin
C’est masculine ou fémininshzahedi
 
Cómo Empezar un Negocio
Cómo Empezar un NegocioCómo Empezar un Negocio
Cómo Empezar un Negocioseremprendedor
 
Le formel et l’informel en français
Le formel et l’informel en françaisLe formel et l’informel en français
Le formel et l’informel en françaisshzahedi
 
Parte de un equipo de coumputo
Parte de un equipo de coumputoParte de un equipo de coumputo
Parte de un equipo de coumputoDaniel Paez
 
El uso de las herramientas web 3.0 en los centros educativos del país.
El uso de las herramientas web 3.0 en los centros educativos del país.El uso de las herramientas web 3.0 en los centros educativos del país.
El uso de las herramientas web 3.0 en los centros educativos del país.rocioyandun
 

En vedette (20)

Université : pour une nouvelle ambition
Université : pour une nouvelle ambition Université : pour une nouvelle ambition
Université : pour une nouvelle ambition
 
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0
Presentation reseaux sociaux_twitter_hsabre_ver2 2_cc3 0
 
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !
Ma « Mini-Retraite » d’1 Mois au Maroc en Tant que Technomade !
 
L'histoire de Lyon
L'histoire de Lyon L'histoire de Lyon
L'histoire de Lyon
 
sgbd
sgbdsgbd
sgbd
 
Menú Boquitas
Menú BoquitasMenú Boquitas
Menú Boquitas
 
Dbs ftp
Dbs ftpDbs ftp
Dbs ftp
 
Présentation Mind Fruits, L'agence qui digitalise votre Marketing
Présentation Mind Fruits, L'agence qui digitalise votre MarketingPrésentation Mind Fruits, L'agence qui digitalise votre Marketing
Présentation Mind Fruits, L'agence qui digitalise votre Marketing
 
-Stage metayer morgane
-Stage metayer morgane-Stage metayer morgane
-Stage metayer morgane
 
choix des prothèses aortiques cardiaques
choix des prothèses aortiques cardiaqueschoix des prothèses aortiques cardiaques
choix des prothèses aortiques cardiaques
 
Distribución normal
Distribución normalDistribución normal
Distribución normal
 
C’est masculine ou féminin
C’est masculine ou fémininC’est masculine ou féminin
C’est masculine ou féminin
 
Cómo Empezar un Negocio
Cómo Empezar un NegocioCómo Empezar un Negocio
Cómo Empezar un Negocio
 
Tarot brochure
Tarot brochureTarot brochure
Tarot brochure
 
Le formel et l’informel en français
Le formel et l’informel en françaisLe formel et l’informel en français
Le formel et l’informel en français
 
Parte de un equipo de coumputo
Parte de un equipo de coumputoParte de un equipo de coumputo
Parte de un equipo de coumputo
 
Blogs, forums et wikis
Blogs, forums et wikisBlogs, forums et wikis
Blogs, forums et wikis
 
El uso de las herramientas web 3.0 en los centros educativos del país.
El uso de las herramientas web 3.0 en los centros educativos del país.El uso de las herramientas web 3.0 en los centros educativos del país.
El uso de las herramientas web 3.0 en los centros educativos del país.
 
EM-Premium
EM-PremiumEM-Premium
EM-Premium
 
Video a mestreacasa
Video a mestreacasaVideo a mestreacasa
Video a mestreacasa
 

Similaire à Atelier gwt

RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdf
RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdfRAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdf
RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdfSouf212
 
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbWebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbHINDGUENDOUZ
 
AOP.pptx
AOP.pptxAOP.pptx
AOP.pptxManalAg
 
Utilisation d'une api web avec asp
Utilisation d'une api web avec aspUtilisation d'une api web avec asp
Utilisation d'une api web avec aspNovencia Groupe
 
4 asynch task_services_thread
4 asynch task_services_thread4 asynch task_services_thread
4 asynch task_services_threadSaber LAJILI
 
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...sametmax
 
eServices-Tp2: bpel
eServices-Tp2: bpeleServices-Tp2: bpel
eServices-Tp2: bpelLilia Sfaxi
 
Activity
ActivityActivity
Activitydido
 
Tp1 design patternappliques
Tp1 design patternappliquesTp1 design patternappliques
Tp1 design patternappliquesMariem ZAOUALI
 
NodeJS for Mobile App
NodeJS for Mobile AppNodeJS for Mobile App
NodeJS for Mobile AppHabib MAALEM
 
eServices-Tp1: Web Services
eServices-Tp1: Web ServiceseServices-Tp1: Web Services
eServices-Tp1: Web ServicesLilia Sfaxi
 
SPA avec Angular et SignalR (FR)
SPA avec Angular et SignalR (FR)SPA avec Angular et SignalR (FR)
SPA avec Angular et SignalR (FR)Rui Carvalho
 

Similaire à Atelier gwt (20)

Rapport tp2 j2ee
Rapport tp2 j2eeRapport tp2 j2ee
Rapport tp2 j2ee
 
RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdf
RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdfRAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdf
RAPPORT DU PREMIER MINI PROJET «FORUM DE CHAT» Novembre 2005.pdf
 
.NET DotNet CF - 3
.NET DotNet CF - 3.NET DotNet CF - 3
.NET DotNet CF - 3
 
Soap
SoapSoap
Soap
 
Tutoriel web service
Tutoriel  web serviceTutoriel  web service
Tutoriel web service
 
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbWebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
WebServices.pdfbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 
AOP.pptx
AOP.pptxAOP.pptx
AOP.pptx
 
Utilisation d'une api web avec asp
Utilisation d'une api web avec aspUtilisation d'une api web avec asp
Utilisation d'une api web avec asp
 
4 asynch task_services_thread
4 asynch task_services_thread4 asynch task_services_thread
4 asynch task_services_thread
 
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...
Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Webso...
 
eServices-Tp2: bpel
eServices-Tp2: bpeleServices-Tp2: bpel
eServices-Tp2: bpel
 
8-socket.pdf
8-socket.pdf8-socket.pdf
8-socket.pdf
 
Activity
ActivityActivity
Activity
 
Tutoriel ajax jquery
Tutoriel ajax jqueryTutoriel ajax jquery
Tutoriel ajax jquery
 
Linq Tech Days08 Lux
Linq Tech Days08 LuxLinq Tech Days08 Lux
Linq Tech Days08 Lux
 
Tp1 design patternappliques
Tp1 design patternappliquesTp1 design patternappliques
Tp1 design patternappliques
 
NodeJS for Mobile App
NodeJS for Mobile AppNodeJS for Mobile App
NodeJS for Mobile App
 
eServices-Tp1: Web Services
eServices-Tp1: Web ServiceseServices-Tp1: Web Services
eServices-Tp1: Web Services
 
Rapport tp3 j2ee
Rapport tp3 j2eeRapport tp3 j2ee
Rapport tp3 j2ee
 
SPA avec Angular et SignalR (FR)
SPA avec Angular et SignalR (FR)SPA avec Angular et SignalR (FR)
SPA avec Angular et SignalR (FR)
 

Plus de Université de Sherbrooke (6)

Tuto jtatoo
Tuto jtatooTuto jtatoo
Tuto jtatoo
 
Eclipse
EclipseEclipse
Eclipse
 
Rapport de fin d'etude
Rapport  de fin d'etudeRapport  de fin d'etude
Rapport de fin d'etude
 
How to install gwt and maven
How to install gwt and maven How to install gwt and maven
How to install gwt and maven
 
J2ee
J2eeJ2ee
J2ee
 
Presentation de gwt maven
Presentation de  gwt mavenPresentation de  gwt maven
Presentation de gwt maven
 

Atelier gwt

  • 2. Objectif Création une application basic avec GWT pour familiarise avec le Framework Description Dans ce TP on vas crée une application StockWatcher les principes fonctionnements de l’application sont :  Permet aux utilisateurs la possibilité d'ajouter des actions  Afficher les informations suivantes pour chaque stock: symbole, le cours, le changement depuis le dernier rafraîchissement  Fournir aux utilisateurs la possibilité de supprimer un support dans la liste Actualiser le prix des actions  Calculer la variation depuis la dernière actualisation à la fois comme un nombre et un pourcentage  Afficher un horodatage indiquant la dernière mise à jour
  • 3. Les éléments d'interface utilisateur:  une table pour contenir les données de stock  deux boutons, l'un pour ajouter des actions et un pour les supprimer  une zone de saisie pour entrer le code de stock  un timestamp pour afficher l'heure et la date de la dernière actualisation Les étapes de créations de l’application  Creation d’un nouveau projet  création d’interface utilisateur  manager les événements  debug l’application  application d’un style (css)  complies l’application  client-serveur communication (RPC) Ajout du plugin mojo
  • 4. Création du projet GWT avec Maven
  • 5. Client serveur communication RPC Principe de fonctionnement Code GWT On demande un service mais on n’attend pas la réponse Interface asynchrone Celle-ci viendra en son temps grâce à un « objet de rappel ». Interface synchrone Code Serveur Créer un service  Coté client, définir une interface dite synchrone qui étend RemoteService et qui liste toutes les méthodes RPC  Coté serveur, implémenter l’interface et étendre RemoteServiceServlet  Coté client, définir une interface asynchrone basée sur la première interface avec le même nombre de méthodes que la première interface
  • 6. Interface synchrone coté client  Spécification de vos services Import com.google.gwt.user.client.rpc.RemoteService; public interface MyService extends RemoteService { public T myMethod(T1 p1, T2 p2, T3 p3); } Implémentation coté serveur  Implémentation de vos services public class MyServiceImpl extends RemoteServiceServlet implements MyService { public T myMethod(T1 p1, T2 p2, T2 p3) { // … return r; } } Interface asynchrone coté client  Implémentation de vos services interface MyServiceAsync { public void myMethod(T1 p1, T2 p2,T2 p3, AsyncCallback<T> callback); }
  • 7. Appel de méthodes asynchrones o Un appel de méthode asynchrone nécessite de passer un objet de rappel (callback object) o L’objet de rappel est notifié lorsque l’appel asynchrone est terminé o En attendant l’appelant continu son activité o Remarquez que les méthodes asynchrones ont un type résultat void o Conventions de nommage o Nom des classes et interfaces – MyService interface synchrone – MyServiceImpl implementation – MyServiceAsync interface asynchrone o Chaque méthode dans l’interface synchrone doit avoir une méthode correspondante dans l’interface asynchrone avec un paramêtre extra en dernier argument de type AsyncCallback o Méthode de l’interface synchrone public Integer[ ] myMethod(String s, int i) o Méthode de l’interface asynchrone public void myMethod(String s,int i, AsyncCallback<Integer[ ]> callback) Utilisation de services • Créer une instance de service MonServiceAsync monService = GWT.create(MonService.class); • Appel de méthode à distance monService.maMethode(p1,p2, new AsyncCallBack<T>() { public onFailure(Trowable t) {...} public onSuccess(T result) {...} }) Chemin d’accès à un service
  • 8. • Le chemin d’accès à un service est composé de deux parties – /nomDuModule/nomDuService • Le nom du service peut être défini de deux manières – Statiquement par annotation dans l’interface synchrone @RemoteServiceRelativePath("service") – Dynamiquement ServiceAsync service = GWT.create(Service.class); ServiceDefTarget test = (ServiceDefTarget) service test.setServiceEntryPoint("/module/service"); • Les déclarations de path pour la servlet doivent être cohérentes – Dans le descripteur de module <servlet class= "MaServlet" path="/module/service"/> – Dans le descripteur web.xml <url-pattern>/module/service</urlpattern> Application Dans ce mini tutorial nous allons creer une petite application qui implémente le service propose par le framework GWT .Ceer un nouveau projet et suivre les diffférentes etapes decritent . I Configuration Afin de définir et configurer une interface RPC asynchrone, vous aurez besoin de créer trois nouveaux fichiers: 1. MonService Une interface implémentant RemoteService dans laquelle vous définirez les méthodes que vous voudrez appeler. Vous définirez grâce à l’annotation @RemoteServiceRelativePath(String path), le chemin grâce auquel vous accéderez à votre service:Cette classe doit etre créée dans le package client 1 //MonService.java 2 @RemoteServiceRelativePath("monservice")
  • 9. 3 public interface MonService extends RemoteService { 4 String exempleMethode(); 5} Toutes vos méthodes asynchrones doivent avoir un retour de type Serializable ! 2. MonServiceImpl Une classe située dans le package server, étendant RemoteServiceServlet et implémentant MonService, dont vous implémenterez les méthodes : 1 //MonServiceImpl.java public class MonServiceImpl extends RemoteServiceServlet implements Mon 2 Service { 3 4 @Override 5 public String exempleMethode() { 6 return "Réponse du Serveur"; 7 } 8 9} 3. MonServiceAsync Une interface devant être dans le même package que MonService et dont le nom devra être le même que celle-ci suivi de Async (e.g :MonServiceAsync). Dans cette interface, vous définirez les mêmes méthodes que dans MonService, mis a part quelques détails:
  • 10. 1 //MonServiceAsync.java 2 public interface MonServiceAsync { 3 4 void exempleMethode(AsyncCallback<String> callback); 5 6} Comme vous pouvez le voir, la méthode dans cette interface retourne void, donc rien. En effet, toutes vos méthodes dans cette interface auront un type de retour void. Cependant, le type de retour de vos méthodes définies dans MonService se retrouvent dans l’argument supplémentaire de votre méthode : AsyncCallback<String> callback. Toutes vos méthodes définies dans MonService devront donc être ainsi transposées dansMonServiceAsync. Maintenant, afin de pouvoir accéder à notre code côté serveur, nous allons avoir besoin de configurer une servlet qui contiendra l’implémentation de MonService dans le web.xml. Rien de différent ici avec la définition habituelle des servlets en Java. Vous préciserez donc la classe de la servlet, ainsi que son chemin (celui définit dans MonService). <!--MonServiceAsync.java--> 01 02 <servlet> 0 <servlet-name>monServiceImpl</servlet-name> 3 <servlet- 0 class>com.gwtfrance.mapremiereapplication.server.MonServiceImpl</servlet 4 -class> 05 </servlet>
  • 11. 06 07 <servlet-mapping> 08 <servlet-name>monServiceImpl</servlet-name> 09 <url-pattern>/ma_premiere_application/monservice</url-pattern> 10 </servlet-mapping> Voilà, votre application est prête à utiliser les appels asynchrones. Si vous le désirez, maintenant que vous savez à quoi servent les fichiersGreetingService, GreetingServiceAsync, et GreetingServiceImpl, vous pouvez les supprimer, ainsi que la configuration de la servlet greetingServicedans le web.xml. II. Utilisation GWT-RPC étant configuré, nous allons pouvoir effectuer nos appels asynchrones. Pour ceci, vous aurez besoin de créer une instance du proxy de service :Créer une classe dans le package client qui implément le entryPoint :explement :Ma_Premiere_Application.java 1 //Ma_Premiere_Application.java 2 final MonServiceAsync monService = GWT.create(MonService.class); Je vous conseille fortement de faire de cette instance un Singleton, étant inutile de réinstancier systématiquement ce proxy. Afin de pouvoir gérer les retour de notre appel asynchrone, nous aurons besoin d’un objet AsyncCallback. 01 //Ma_Premiere_Application.java 02 final AsyncCallback<String> callback = new AsyncCallback<String>() { 04 @Override
  • 12. 05 public void onFailure(Throwable caught) { 06 Window.alert("Erreur lors de l'appel serveur"); 07 08 } 09 10 @Override 11 public void onSuccess(String result) { 12 Window.alert(result); 13 14 } 15 }; Comme vous pouvez le voir, lors de l’instanciation de notre objet callback, nous devons implémenter deux méthode:  La méthode onFailure(Throwable caught) est appelée lorsque une erreur se produit côté serveur lors de votre appel. Grâce à l’objetThrowable, vous pourrez récupérer les exceptions lancées côté serveur et les traiter comme vous l’entendez.  La méthode onSuccess(String result) est elle appelée lorsque le traitement serveur s’est passé sans problème. L’objet retourné correspond à l’objet retourné par votre implémentation côté serveur. Notre objet callback étant maintenant défini, nous pouvons donc effectuer notre appel asynchrone. Ici, nous remplaçons le code de la méthodeonClick(Event event) par notre appel: 1 //Ma_Premiere_Application.java 2 monBouton.addClickHandler(new ClickHandler() {
  • 13. 3 4 @Override 5 public void onClick(ClickEvent event) { 6 monService.exempleMethode(callback); 7 8 } 9 }); StockWatcher.java package com.google.gwt.sample.stockwatcher.client; import java.util.ArrayList; import java.util.Date; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class StockWatcher implements EntryPoint { private VerticalPanel mainPanel = new VerticalPanel(); private FlexTable stocksFlexTable = new FlexTable(); private HorizontalPanel addPanel = new HorizontalPanel(); private TextBox newSymbolTextBox = new TextBox(); private Button addStockButton = new Button("Add"); private Label lastUpdatedLabel = new Label(); private ArrayList<String> stocks = new ArrayList<String>(); private static final int REFRESH_INTERVAL = 5000; // ms
  • 14. /** * Entry point method. */ public void onModuleLoad() { // Create table for stock data. stocksFlexTable.setText(0, 0, "Symbol"); stocksFlexTable.setText(0, 1, "Price"); stocksFlexTable.setText(0, 2, "Change"); stocksFlexTable.setText(0, 3, "Remove"); // Add styles to elements in the stock list table. stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader"); stocksFlexTable.addStyleName("watchList"); stocksFlexTable.getCellFormatter().addStyleName(0, 1, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(0, 2, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(0, 3, "watchListRemoveColumn"); // Assemble Add Stock panel. addPanel.add(newSymbolTextBox); addPanel.add(addStockButton); addPanel.addStyleName("addPanel"); // Assemble Main panel. mainPanel.add(stocksFlexTable); mainPanel.add(addPanel); mainPanel.add(lastUpdatedLabel); // Associate the Main panel with the HTML host page. RootPanel.get("stockList").add(mainPanel); // Move cursor focus to the input box. newSymbolTextBox.setFocus(true); // Setup timer to refresh list automatically. Timer refreshTimer = new Timer() { @Override public void run() { refreshWatchList(); } }; refreshTimer.scheduleRepeating(REFRESH_INTERVAL); //Listen for mouse events on the Add button. newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() { public void onKeyPress(KeyPressEvent event) { // if (event.getCharCode() == KeyCodes.KEY_ENTER) { addStock(); // } } }); } /** * Add stock to FlexTable. Executed when the user clicks the addStockButton or * presses enter in the newSymbolTextBox. */ private void addStock() { final String symbol = newSymbolTextBox.getText().toUpperCase().trim(); newSymbolTextBox.setFocus(true); // Stock code must be between 1 and 10 chars that are numbers, letters, or dots. if (!symbol.matches("^[0-9A-Z.]{1,10}$")) {
  • 15. Window.alert("'" + symbol + "' is not a valid symbol."); newSymbolTextBox.selectAll(); return; } newSymbolTextBox.setText(""); // Don't add the stock if it's already in the table. if (stocks.contains(symbol)) return; // Add the stock to the table. int row = stocksFlexTable.getRowCount(); stocks.add(symbol); stocksFlexTable.setText(row, 0, symbol); stocksFlexTable.getCellFormatter().addStyleName(row, 1, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(row, 2, "watchListNumericColumn"); stocksFlexTable.getCellFormatter().addStyleName(row, 3, "watchListRemoveColumn"); // Add a button to remove this stock from the table. Button removeStockButton = new Button("x"); removeStockButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { int removedIndex = stocks.indexOf(symbol); stocks.remove(removedIndex); stocksFlexTable.removeRow(removedIndex + 1); } }); stocksFlexTable.setWidget(row, 3, removeStockButton); // Get the stock price. refreshWatchList(); } /** * Update a single row in the stock table. * * @param price Stock data for a single row. */ private void updateTable(StockPrice price) { // Make sure the stock is still in the stock table. if (!stocks.contains(price.getSymbol())) { return; } int row = stocks.indexOf(price.getSymbol()) + 1; // Format the data in the Price and Change fields. String priceText = NumberFormat.getFormat("#,##0.00").format( price.getPrice()); NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00"); String changeText = changeFormat.format(price.getChange()); String changePercentText = changeFormat.format(price.getChangePercent()); // Populate the Price and Change fields with new data. stocksFlexTable.setText(row, 1, priceText); stocksFlexTable.setText(row, 2, changeText + " (" + changePercentText + "%)"); } private void refreshWatchList() { final double MAX_PRICE = 100.0; // $100.00 final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
  • 16. StockPrice[] prices = new StockPrice[stocks.size()]; for (int i = 0; i < stocks.size(); i++) { double price = Random.nextDouble() * MAX_PRICE; double change = price * MAX_PRICE_CHANGE * (Random.nextDouble() * 2.0 - 1.0); prices[i] = new StockPrice(stocks.get(i), price, change); } updateTable(prices); } private void updateTable(StockPrice[] prices) { for (int i = 0; i < prices.length; i++) { updateTable(prices[i]); } // Display timestamp showing last refresh. lastUpdatedLabel.setText("Last update : " + DateTimeFormat.getMediumDateTimeFormat().format(new Date())); } } StockWatcher.css /* Formatting specific to the StockWatcher application */ body { padding: 10px; } /* stock list header row */ .watchListHeader { background-color: #2062B8; color: white; font-style: italic; } /* stock list flex table */ .watchList { border: 1px solid silver; padding: 2px; margin-bottom:6px; } /* stock list Price and Change fields */ .watchListNumericColumn { text-align: right; width:8em; } /* stock list Remove column */ .watchListRemoveColumn { text-align: center; } /* Add Stock panel */ .addPanel { margin: 10px 0px 15px 0px; }