Communication GWT - RPC

Une application basée sur GWT est généralement constituée d'un module côté client et d'un module côté serveur. Le code côté client s'exécute dans le navigateur et le code côté serveur s'exécute dans le serveur Web. Le code côté client doit faire une requête HTTP sur le réseau pour accéder aux données côté serveur.

RPC, Remote Procedure Call est le mécanisme utilisé par GWT dans lequel le code client peut exécuter directement les méthodes côté serveur.

  • GWT RPC est basé sur un servlet.

  • GWT RPC est asynchrone et le client n'est jamais bloqué pendant la communication.

  • En utilisant GWT RPC, les objets Java peuvent être envoyés directement entre le client et le serveur (qui sont automatiquement sérialisés par le framework GWT).

  • Le servlet côté serveur est appelé service.

  • L'appel de procédure à distance qui appelle les méthodes des servlets côté serveur à partir du code côté client est appelé invoking a service.

Composants GWT RPC

Voici les trois composants utilisés dans le mécanisme de communication GWT RPC

  • Un service distant (servlet côté serveur) qui s'exécute sur le serveur.
  • Code client pour appeler ce service.
  • Objets de données Java qui seront transmis entre le client et le serveur.

Le client et le serveur GWT sérialisent et désérialisent automatiquement les données afin que les développeurs ne soient pas obligés de sérialiser / désérialiser les objets et les objets de données peuvent voyager via HTTP.

Le diagramme suivant montre l'architecture RPC.

Pour commencer à utiliser RPC, nous devons suivre les conventions GWT.

Flux de travail de communication RPC

Étape 1 - Créer une classe de modèle sérialisable

Définissez un objet de modèle Java côté client qui doit être sérialisable.

public class Message implements Serializable {
   ...
   private String message;
   public Message(){};

   public void setMessage(String message) {
      this.message = message;
   }
   ...
}

Étape 2 - Créer une interface de service

Définissez une interface pour le service côté client qui étend RemoteService répertoriant toutes les méthodes de service.

Utilisez l'annotation @RemoteServiceRelativePath pour mapper le service avec un chemin par défaut du servlet distant par rapport à l'URL de base du module.

@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
   Message getMessage(String input);
}

Étape 3 - Créer une interface de service asynchrone

Définissez une interface asynchrone pour le service côté client (au même emplacement que le service mentionné ci-dessus) qui sera utilisée dans le code client GWT.

public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

Étape 4 - Créer une classe de servlet d'implémentation de service

Implémentez l'interface côté serveur et cette classe doit étendre la classe RemoteServiceServlet.

public class MessageServiceImpl extends RemoteServiceServlet
   implements MessageService{
   ...
   public Message getMessage(String input) {
      String messageString = "Hello " + input + "!";
      Message message = new Message();
      message.setMessage(messageString);
      return message;
   }
}

Étape 5 - Mettez à jour Web.xml pour inclure la déclaration de servlet

Modifiez le descripteur de déploiement de l'application Web (web.xml) pour inclure la déclaration de servlet MessageServiceImpl.

<web-app>
   ...
   <servlet>
      <servlet-name>messageServiceImpl</servlet-name>
      <servlet-class>com.tutorialspoint.server.MessageServiceImpl
      </servlet-class>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>messageServiceImpl</servlet-name>
      <url-pattern>/helloworld/message</url-pattern>
   </servlet-mapping>
</web-app>

Étape 6 - Faire l'appel de procédure à distance dans le code d'application

Créez la classe de proxy de service.

MessageServiceAsync messageService = GWT.create(MessageService.class);

Créez le gestionnaire AsyncCallback pour gérer le rappel RPC dans lequel le serveur renvoie le message au client

class MessageCallBack implements AsyncCallback<Message> {

   @Override
   public void onFailure(Throwable caught) {
      Window.alert("Unable to obtain server response: "
      + caught.getMessage());	
   }

   @Override
   public void onSuccess(Message result) {
      Window.alert(result.getMessage()); 
   }	   
}

Appeler le service à distance lorsque l'utilisateur interagit avec l'interface utilisateur

public class HelloWorld implements EntryPoint {
   ... 
   public void onModuleLoad() {
   ...
      buttonMessage.addClickHandler(new ClickHandler() {			
         @Override
         public void onClick(ClickEvent event) {
            messageService.getMessage(txtName.getValue(), 
            new MessageCallBack());
         }
      });
   ...
   }
}

Exemple complet de communication RPC

Cet exemple vous guidera à travers des étapes simples pour montrer un exemple de communication RPC dans GWT. Suivez les étapes suivantes pour mettre à jour l'application GWT que nous avons créée dans GWT - Chapitre Créer une application -

Étape La description
1 Créez un projet avec un nom HelloWorld sous un package com.tutorialspoint comme expliqué dans le chapitre GWT - Créer une application .
2 Modifiez HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html et HelloWorld.java comme expliqué ci-dessous. Gardez le reste des fichiers inchangé.
3 Compilez et exécutez l'application pour vérifier le résultat de la logique implémentée.

Voici le contenu du descripteur de module modifié src/com.tutorialspoint/HelloWorld.gwt.xml.

<?xml version = "1.0" encoding = "UTF-8"?>
<module rename-to = 'helloworld'>
   <!-- Inherit the core Web Toolkit stuff.                        -->
   <inherits name = 'com.google.gwt.user.User'/>

   <!-- Inherit the default GWT style sheet.                       -->
   <inherits name = 'com.google.gwt.user.theme.clean.Clean'/>
   <!-- Inherit the UiBinder module.                               -->
   <inherits name = "com.google.gwt.uibinder.UiBinder"/>
   <!-- Specify the app entry point class.                         -->
   <entry-point class = 'com.tutorialspoint.client.HelloWorld'/>
  
   <!-- Specify the paths for translatable code                    -->
   <source path = 'client'/>
   <source path = 'shared'/>

</module>

Voici le contenu du fichier de feuille de style modifié war/HelloWorld.css.

body {
   text-align: center;
   font-family: verdana, sans-serif;
}

h1 {
   font-size: 2em;
   font-weight: bold;
   color: #777777;
   margin: 40px 0px 70px;
   text-align: center;
}

Voici le contenu du fichier hôte HTML modifié war/HelloWorld.html.

<html>
   <head>
      <title>Hello World</title>
      <link rel = "stylesheet" href = "HelloWorld.css"/>
      <script language = "javascript" src = "helloworld/helloworld.nocache.js">
      </script>
   </head>

   <body>
      <h1>RPC Communication Demonstration</h1>
      <div id = "gwtContainer"></div>
   </body>
</html>

Créez maintenant le fichier Message.java dans le src/com.tutorialspoint/client emballage et placez-y le contenu suivant

package com.tutorialspoint.client;

import java.io.Serializable;

public class Message implements Serializable {
 
   private static final long serialVersionUID = 1L;
   private String message;
   public Message(){};

   public void setMessage(String message) {
      this.message = message;
   }

   public String getMessage() {
      return message;
   }
}

Créez maintenant le fichier MessageService.java dans le src/com.tutorialspoint/client emballage et placez-y le contenu suivant

package com.tutorialspoint.client;

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

@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
   Message getMessage(String input);
}

Créez maintenant le fichier MessageServiceAsync.java dans le src/com.tutorialspoint/client emballage et placez-y le contenu suivant

package com.tutorialspoint.client;

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

public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

Créez maintenant le fichier MessageServiceImpl.java dans le src/com.tutorialspoint/server emballage et placez-y le contenu suivant

package com.tutorialspoint.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.tutorialspoint.client.Message;
import com.tutorialspoint.client.MessageService;

public class MessageServiceImpl extends RemoteServiceServlet 
   implements MessageService{

   private static final long serialVersionUID = 1L;

   public Message getMessage(String input) {
      String messageString = "Hello " + input + "!";
      Message message = new Message();
      message.setMessage(messageString);
      return message;
   }   
}

Mettre à jour le contenu du descripteur de déploiement d'application Web modifié war/WEB-INF/web.xml pour inclure la déclaration de servlet MessageServiceImpl.

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE web-app
   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
   "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
   <!-- Default page to serve -->
   <welcome-file-list>
      <welcome-file>HelloWorld.html</welcome-file>
   </welcome-file-list>
   
   <servlet>
      <servlet-name>messageServiceImpl</servlet-name>
      <servlet-class>com.tutorialspoint.server.MessageServiceImpl
      </servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>messageServiceImpl</servlet-name>
      <url-pattern>/helloworld/message</url-pattern>
   </servlet-mapping>
</web-app>

Remplacez le contenu de HelloWorld.java dans src/com.tutorialspoint/client paquet avec ce qui suit

package com.tutorialspoint.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
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.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
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 HelloWorld implements EntryPoint {
	
   private MessageServiceAsync messageService = 
   GWT.create(MessageService.class);

   private class MessageCallBack implements AsyncCallback<Message> {
      @Override
      public void onFailure(Throwable caught) {
         /* server side error occured */
         Window.alert("Unable to obtain server response: " + caught.getMessage());	
      }
      @Override
      public void onSuccess(Message result) {
          /* server returned result, show user the message */
         Window.alert(result.getMessage());
      }	   
   }

   public void onModuleLoad() {
      /*create UI */
      final TextBox txtName = new TextBox(); 
      txtName.setWidth("200");
      txtName.addKeyUpHandler(new KeyUpHandler() {
         @Override
         public void onKeyUp(KeyUpEvent event) {
            if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){
               /* make remote call to server to get the message */
               messageService.getMessage(txtName.getValue(), 
               new MessageCallBack());
            }				
         }
      });
      Label lblName = new Label("Enter your name: ");

      Button buttonMessage = new Button("Click Me!");

      buttonMessage.addClickHandler(new ClickHandler() {			
         @Override
         public void onClick(ClickEvent event) {
            /* make remote call to server to get the message */
            messageService.getMessage(txtName.getValue(), 
            new MessageCallBack());
         }
      });

      HorizontalPanel hPanel = new HorizontalPanel();	
      hPanel.add(lblName);
      hPanel.add(txtName);
      hPanel.setCellWidth(lblName, "130");

      VerticalPanel vPanel = new VerticalPanel();
      vPanel.setSpacing(10);
      vPanel.add(hPanel);
      vPanel.add(buttonMessage);
      vPanel.setCellHorizontalAlignment(buttonMessage, 
      HasHorizontalAlignment.ALIGN_RIGHT);

      DecoratorPanel panel = new DecoratorPanel();
      panel.add(vPanel);

      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }    
}

Une fois que vous êtes prêt avec tous les changements effectués, laissez-nous compiler et exécuter l'application en mode développement comme nous l'avons fait dans le chapitre GWT - Créer une application . Si tout va bien avec votre application, cela produira le résultat suivant -