GWTで非同期通信 RPC(Remote Procedure Call)覚書

非同期通信の内部の動きとは知らなくていいがルールは知っておいたほうがいいので覚書。
でも結局内部ロジックが気になってきたのでなんとなく書いてみた。

■GreetingServiceとGreetingServiceAsyncについて
GWTではクライアントとサーバの通信にRPC(Remote Procedure Call)という仕組みを使っています。

  • クライアント:GwtSampleEchoBack(例)
  • サーバ:GreetingServiceImpl

GWTのデータ通信
クライアントはGreetingServiceAsyncを使ってサーバのメソッドを呼び出す(リモートサービスの呼び出し)。
サーバはメソッドが呼ばれるとクライアントからの呼び出しを受信する。
処理結果を戻り値として返す。

■Serviceインターフェース
GWTには2つのSeviceインタフェースがある。

  • GreetingService:サーバが提供するサービス
  • GreetingServiceAsync:リモートサービスの呼び出しを提供するサービス

それぞれのインターフェースは対になっていて、インターフェースを使って非同期通信を可能にしている。
■サービスインターフェースのルール

  • GreetingServiceGreetingServiceAsyncのメソッド名は同じにする
  • GreetingServiceAsyncvoidにする
  • GreetingServiceAsyncの引数はGreetingServiceの引数にAsyncCallback<[GreetingServiceの戻り値]> callbackを加えたもの

■RPC覚書(詳しいことは分からなくていいけどこの辺は知っておけ的なこと)

  • サービスインターフェースのルール(上記参照)
  • RPCを使うときはクライアントにGreetingServiceAsyncを持たせる
GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
  • サーバGreetingServiceImplはGreetingServiceインターフェースを実装している。
public class GreetingServiceImpl extends RemoteServiceServlet implements
		GreetingService {
  • リモートサービスの呼び出しはgreetingService.[呼び出したいメソッド]を使う
greetingService.echoback(nameField.getText(), callback);
  • GreetingServiceAsync側の引数AsyncCallback callbackは非同期通信の結果が格納される
  • AsyncCallbackはonFailure、onSuccessメソッドをオーバライドする
@Override
public void onFailure(Throwable caught) {
	//失敗 サーバ側で例外が発生するとこっちにくる
}

@Override
public void onSuccess(String result) {
	//成功
}
  • onFailureはサーバで例外が発生したときに呼ばれる。caughtはException e的とおなじ
  • onSuccessは非同期通信が成功したときに呼ばれる。
    • 処理結果の戻り値は引数resultに格納されている。

■非同期通信ロジックダイジェスト(たぶん)

  • クライアント側はGreetingServiceAsyncのメソッドを使ってリモートサービスを呼び出す
  • GreetingServiceインターフェースを実装したサーバGreetingServiceImplの対となるメソッドが呼ばれる。
  • サーバで処理云々
  • 処理成功→onSuccessをコールバック
    • 処理結果の戻り値は引数resultに格納されている
  • 処理成功→onFailureをコールバック
    • 例外が発生したときはこっち。引数caughtはException e的なもの

ここでは書いていないが実際はSerivceProxyクラスがいてクライアント・サーバの通信の橋渡し的なことをしている。
「リモートサービスの呼び出し」→「ProxyService」→「ServiceImpl」
かなりいい加減だけどこんな感じなことしてんのかな?(信じないでください)

<span style="font-weight:bold;">■Client</span>
greetingService = GWT.create(GreetingService.class);  【1へ飛ぶ】
greetingService.greet(); 【2へ飛ぶ】
〜略〜
//callback作成
AsyncCallback<String> callback = new AsyncCallback<String>(){

	【5失敗用コールバック】
	@Override
	public void onFailure(Throwable caught) {
		//例外発生
	}

	【4成功用コールバック】
	@Override
	public void onSuccess(String result) {
		//成功
	}
};

<span style="font-weight:bold;">■SerivceProxy </span>
public class SerivceProxy implements GreetingServiceAsync{
	private static GreetingService service;
	static SerivceProxy instance = new SerivceProxy();
	
	【1呼び出される】
	public static SerivceProxy create(GreetingService s){
		service = s;
		return instance;
	}
	
	【2呼び出される】
	@Override
	public void greetServer(String input, AsyncCallback<String> callback) {
		try{
			String result = service.greetServer(input);【3へ飛ぶ】
			callback.onSuccess(result);	【4へ飛ぶ】
		}catch(Exception e){
			callback.onFailure(e);  【5へ飛ぶ】
		}
	}
}

<span style="font-weight:bold;">■GreetingServiceImpl </span>
public class GreetingServiceImpl extends RemoteServiceServlet implements
		GreetingService {

	【3呼び出される】
	public String greetServer(String input) {
		return "You typed " + input + "!<br>";
	}
}