GWT - Comunicação RPC

Um aplicativo baseado em GWT geralmente consiste em um módulo do lado do cliente e um módulo do lado do servidor. O código do lado do cliente é executado no navegador e o código do lado do servidor é executado no servidor da web. O código do lado do cliente deve fazer uma solicitação HTTP através da rede para acessar os dados do lado do servidor.

RPC, Remote Procedure Call é o mecanismo usado pelo GWT no qual o código do cliente pode executar diretamente os métodos do lado do servidor.

  • O GWT RPC é baseado em servlet.

  • O GWT RPC é assíncrono e o cliente nunca é bloqueado durante a comunicação.

  • Usando GWT RPC, objetos Java podem ser enviados diretamente entre o cliente e o servidor (que são serializados automaticamente pela estrutura GWT).

  • O servlet do lado do servidor é denominado como service.

  • A chamada de procedimento remoto que chama métodos de servlets do lado do servidor a partir do código do lado do cliente é conhecida como invoking a service.

Componentes GWT RPC

A seguir estão os três componentes usados ​​no mecanismo de comunicação GWT RPC

  • Um serviço remoto (servlet do lado do servidor) que é executado no servidor.
  • Código do cliente para invocar esse serviço.
  • Objetos de dados Java que serão transmitidos entre cliente e servidor.

O cliente e o servidor GWT serializam e desserializam dados automaticamente para que os desenvolvedores não sejam obrigados a serializar / desserializar objetos e os objetos de dados podem trafegar por HTTP.

O diagrama a seguir mostra a arquitetura RPC.

Para começar a usar o RPC, devemos seguir as convenções do GWT.

Fluxo de trabalho de comunicação RPC

Etapa 1 - Criar uma classe de modelo serializável

Defina um objeto de modelo java no lado do cliente que deve ser serializável.

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

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

Etapa 2 - Criar uma interface de serviço

Defina uma interface para serviço no lado do cliente que estenda RemoteService listando todos os métodos de serviço.

Use a anotação @RemoteServiceRelativePath para mapear o serviço com um caminho padrão de servlet remoto relativo à URL base do módulo.

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

Etapa 3 - Criar uma interface de serviço assíncrona

Defina uma interface assíncrona para o serviço no lado do cliente (no mesmo local do serviço mencionado acima) que será usada no código do cliente GWT.

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

Etapa 4 - Criar uma classe de servlet de implementação de serviço

Implemente a interface no lado do servidor e essa classe deve estender a 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;
   }
}

Etapa 5 - Atualizar Web.xml para incluir a declaração de servlet

Edite o descritor de implementação do aplicativo da web (web.xml) para incluir a declaração MessageServiceImpl Servlet.

<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>

Etapa 6 - Faça a chamada de procedimento remoto no Código do Aplicativo

Crie a classe de proxy de serviço.

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

Crie o Manipulador AsyncCallback para lidar com o retorno de chamada RPC no qual o servidor retorna a Mensagem ao cliente

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()); 
   }	   
}

Chamar serviço remoto quando o usuário interagir com a IU

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

Exemplo completo de comunicação RPC

Este exemplo irá guiá-lo através de etapas simples para mostrar um exemplo de uma comunicação RPC no GWT. Siga as etapas a seguir para atualizar o aplicativo GWT que criamos no GWT - capítulo Criar aplicativo -

Degrau Descrição
1 Crie um projeto com o nome HelloWorld em um pacote com.tutorialspoint conforme explicado no capítulo GWT - Criar aplicativo .
2 Modifique HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html e HelloWorld.java conforme explicado abaixo. Mantenha o resto dos arquivos inalterados.
3 Compile e execute o aplicativo para verificar o resultado da lógica implementada.

A seguir está o conteúdo do descritor do módulo modificado 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>

A seguir está o conteúdo do arquivo de folha de estilo modificado 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;
}

A seguir está o conteúdo do arquivo host HTML modificado 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>

Agora crie o arquivo Message.java no src/com.tutorialspoint/client pacote e coloque o seguinte conteúdo nele

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;
   }
}

Agora crie o arquivo MessageService.java no src/com.tutorialspoint/client pacote e coloque o seguinte conteúdo nele

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);
}

Agora crie o arquivo MessageServiceAsync.java no src/com.tutorialspoint/client pacote e coloque o seguinte conteúdo nele

package com.tutorialspoint.client;

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

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

Agora crie o arquivo MessageServiceImpl.java no src/com.tutorialspoint/server pacote e coloque o seguinte conteúdo nele

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;
   }   
}

Atualize o conteúdo do descritor de implementação de aplicativo da web modificado war/WEB-INF/web.xml para incluir a declaração MessageServiceImpl Servlet.

<?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>

Substitua o conteúdo de HelloWorld.java em src/com.tutorialspoint/client pacote com o seguinte

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);
   }    
}

Quando você estiver pronto com todas as alterações feitas, vamos compilar e rodar o aplicativo em modo de desenvolvimento como fizemos no capítulo GWT - Criar Aplicativo . Se tudo estiver bem com sua aplicação, isso produzirá o seguinte resultado -