2010年4月11日日曜日

GoogleAppEngine-RPCの使い方


前回のJDOQLクエリフィルタに引き続き、RPCによるGWTとサーバーの通信を実装します。RPCとは簡単に言うと、クライアントとサーバーでJavaのクラスをそのままやりとりするための通信方式です。

通常AJAXでの通信はXMLもしくはJSOPで行いますが、通信毎にプロトコルの仕様を決めなければなりませんでした。しかしGoogleAppEngineJavaはクライアント画面のGWTとサーバーの両方で使えるJavaのクラスを定義すれば簡単にデータのやりとりができます。

RPCでの通信を行うにはいくつか準備する必要があります。

・通信でやりとりされるオブジェクト
・RemoteServiceインターフェースとサーバー側の実装
・通信結果を受け取る非同期インターフェース

今回はつぶやき情報をサーバーに送る機能を実装してみようかと思います。

TweetPutParam.java
---------------------------

package com.devtter.client.rpc;
import com.google.gwt.user.client.rpc.IsSerializable;

public class TweetPutParam implements IsSerializable {
public String tweet;
public double x;
public double y;
public double z;
}

このクラスはつぶやきと、つぶやいた位置情報を保持しています。ここでのポイントはcom.google.gwt.user.client.rpc.IsSerializableクラスをimplemntsしていることです。このインターフェースを使うだけでコンパイル時にシリアライズ処理が実装されるようです。

TweetService.java
---------------------------

package com.devtter.client.rpc;

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

@RemoteServiceRelativePath("tweet")
public interface TweetService extends RemoteService {
public String put(TweetPutParam param) throws IllegalArgumentException;
}


TweetServiceAsync.java
---------------------------

package com.devtter.client.rpc;

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

public interface TweetServiceAsync {
void put(TweetPutParam param, AsyncCallback callback)
throws IllegalArgumentException;
}


ここまでがインターフェースの定義です。サーバー側では定義されたTweetServiceをサーブレットとして実装します。具体的にはRPCを処理するcom.google.gwt.user.server.rpc.RemoteServiceServletを実装します。
今回のサンプルではクライアントでつぶやかれた内容をJDOに格納します。

TweetServiceImpl.java
---------------------------

package com.devtter.server.rpc;

import com.devtter.server.model.Tweet;
import com.devtter.server.model.TweetDAO;
import com.devtter.client.rpc.TweetGetParam;
import com.devtter.client.rpc.TweetPutParam;
import com.devtter.client.rpc.TweetResponse;
import com.devtter.client.rpc.TweetService;
import com.devtter.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.util.logging.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

@SuppressWarnings("serial")
public class TweetServiceImpl extends RemoteServiceServlet implements TweetService {
private static final Logger log = Logger.getLogger(TweetServiceImpl.class.getName());

public String put(TweetPutParam param) throws IllegalArgumentException{
if (!FieldVerifier.isValidTweet(param.tweet)) {
throw new IllegalArgumentException(
"Tweet must be at less 140 characters long");
}
log.info("put : " + param.tweet);
TweetDAO.tweetAnonymous(param.tweet);
return "";
}
}


次にクライアント側で、つぶやきを送る処理を実装します。実装はちょっと難解な書き方をしますが、まずTweetServiceAsyncをGWTクラスから生成します。これで呼び出す準備ができます。次に実際にコールするときはパラメータとレスポンスを指定することで呼び出すことができます。

TweetPanel.java
---------------------------

private final TweetServiceAsync tweetService = GWT
.create(TweetService.class);

public void sendTweetToServer() {
TweetPutParam putParam = new TweetPutParam();
putParam.tweet = inputPanel.inputBox.getText();
if (!FieldVerifier.isValidTweet(putParam.tweet)) {
return;
}

tweetService.put(putParam,
new AsyncCallback() {
public void onFailure(Throwable caught) {
}

public void onSuccess(String result) {
}
});
}


以上でRPCによるサーバークライアント通信の処理は完了です。慣れるまで敷居が高いですが、一度作ってしまえば、通信内容を変更する時は通信クラスのパラメータをかえるだけで対応出きるのでとても便利です。

なお、今回作ったプログラムは下記に置いてあります
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/client/rpc
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/server/rpc
http://code.google.com/p/devtter/source/browse/#svn/trunk/devtter/src/com/devtter/client/ui/tweet

0 件のコメント:

コメントを投稿