GWTで非同期通信 RPC(Remote Procedure Call)覚書
非同期通信の内部の動きとは知らなくていいがルールは知っておいたほうがいいので覚書。
でも結局内部ロジックが気になってきたのでなんとなく書いてみた。
■GreetingServiceとGreetingServiceAsyncについて
GWTではクライアントとサーバの通信にRPC(Remote Procedure Call)という仕組みを使っています。
- クライアント:GwtSampleEchoBack(例)
- サーバ:GreetingServiceImpl
■GWTのデータ通信
クライアントはGreetingServiceAsyncを使ってサーバのメソッドを呼び出す(リモートサービスの呼び出し)。
サーバはメソッドが呼ばれるとクライアントからの呼び出しを受信する。
処理結果を戻り値として返す。
■Serviceインターフェース
GWTには2つのSeviceインタフェースがある。
- GreetingService:サーバが提供するサービス
- GreetingServiceAsync:リモートサービスの呼び出しを提供するサービス
それぞれのインターフェースは対になっていて、インターフェースを使って非同期通信を可能にしている。
■サービスインターフェースのルール
- GreetingService、GreetingServiceAsyncのメソッド名は同じにする
- GreetingServiceAsyncはvoidにする
- 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>"; } }