02.GWT-RPC

GWT - Client-Server Communication


Client-Server Communication

  • Communicating with the server via GWT RPC
    Add a call to a server using GWT RPC. You'll learn how to make asynchronous calls, serialize Java objects, and handle exceptions.
  • Make HTTP requests to retrieve JSON data from a server. The same technique can be used to retrieve XML data.



GWT - RPC


What is GWT RPC?

GWT RPC框架可以很容易的讓client和server元件在Java物件與Web應用程式之間相互溝通。通常server-side從client-side調用出一個服務。在執行一個GWT RPC服務是眾所皆知的Java Servlet架構模式。在client-side,將使用自動生成代理類別(automatically-generated proxy class)的方式調用服務。並處理Java 物件序列化(serialization of the Java objects)的方式傳遞方法裡的參數並返回值。

Java components of the GWT RPC Mechanism

設置GWT RPC時,須注意以下三點,在呼叫程序運行於遠程服務器調用上(involved in calling procedures running on remote servers):
  1. the service that runs on the server. (the method you are calling)
  2. the client code that invokes the service.
  3. the Java data objects that pass between the client and server. Both the server and the client have the ability to serialize and deserialize data so the data objects can be passed between them as ordinary text.
GWT RPC Plumbing

GWT-RPC with JPA 實作範例:
 
為了定義RPC接口,須設計三組元件:
  1. 定義一個服務接口(xxxxxService)並繼承RemoteService及列出所有的RPC方法。
  2. 建立一個類別(xxxxxServiceImpl)並繼承RemoteServiceServlet及實作上面創建的服務接口。
  3. 定義一個非同步接口(xxxxxAsync)至你的服務,此稱作client-side code。
  • 一個服務的實作必須繼承RemoteServiceServlet及必須實作相關服務接口。請注意,該服務實作並未實作非同步服務接口。
  • 每個服務實作最終是一個Servlet,但不是HttpServlet的擴展,它是由RemoteServiceServlet來替代。
  • RemoteServiceServlet自動處理資料序列化(automatically handles serialization of the data)在client和server之間傳遞和調用服務實現的方法。

------------------------定義服務接口:------------------------
package org.kuoying.client;

import org.kuoying.db.RpcItem;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
 * The client side stub for the RPC service.
 */
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
    void save(RpcItem ri);
}
------------------------定義ServiceImpl實作類別:------------------------
package org.kuoying.server;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.kuoying.client.GreetingService;
import org.kuoying.db.RpcItem;
import org.kuoying.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
public class GreetingServiceImpl extends RemoteServiceServlet implements
        GreetingService {
    private static final long serialVersionUID = 1L;
    @Override
    public void save(RpcItem ri) {    
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("oo");
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(ri);
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }
}
------------------------定義非同步接口:------------------------
package org.kuoying.client;

import org.kuoying.db.RpcItem;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * The client side stub for the RPC service.
 */
public interface GreetingServiceAsync {
    void save(RpcItem ri, AsyncCallback<Void> callback);
}
------------------------佈局Entry Point類別:------------------------
package org.kuoying.client;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.kuoying.db.RpcItem;
import org.kuoying.shared.FieldVerifier;
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.DialogBox;
import com.google.gwt.user.client.ui.HTML;
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;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class First implements EntryPoint {
    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        Button sendButton = new Button("Send");
        final TextBox nameField = new TextBox();
        nameField.setText("GWT User");
        RootPanel.get("nameFieldContainer").add(nameField);
        RootPanel.get("sendButtonContainer").add(sendButton);
        sendButton.addClickHandler(new ClickHandler(){
            GreetingServiceAsync greetingService = GWT
            .create(GreetingService.class);        
            public void onClick(ClickEvent event) {
                String textToServer = nameField.getText();
                RpcItem ri = new RpcItem();
                ri.setId(2);
                ri.setUsername(textToServer);
                
                greetingService.save(ri, new AsyncCallback() {
                    public void onFailure(Throwable caught) {
                        Window.alert("Fail");
                    }
                    @Override
                    public void onSuccess(Object result) {
                        Window.alert("Success");
                    }
                });
            }
        });
    }
}





GWT-Client vs Server

  • 分為 client 端以及可有可無的 server 端
  • GWT Client 的變動只要 hosted browser reload 就可以看到結果.
  • GWT Server 的變動需要 restart server, GWT Server 實際上是一個 servlet, 與 GWT compiler 無關
  • xxx.gwt.xml => 配置模組(Model)路徑、入口處(Entry Point)、繼承、附加CSS及JS等用途。





JSON


JSONP
Comments