GrailsGWTを連携させるGWT Pluginを試してみました。

  • GWTファイル(クライアントクラス、.gwt.xml)の自動生成
  • GrailsサービスをGWT RPCのサービスとして公開する
  • クライアント用サービスのインタフェース、プロキシインタフェースの自動生成

こんな感じのことをやってくれます。以下は、ほとんどPuginのサイトのままですが実際に試してみたときのメモです。

インストール

  1. GWTのバージョン1.4をダウンロードしてインストールします。
  2. GWT_HOMEにインストールパスを設定します。
  3. プロジェクトフォルダにて、
grails install-plugin gwt

を実行してGWTプラグインをインストールします。

モジュールの生成

    
を実行します。モジュール名はパッケージを含むアプリケーション名を指定します("sample.MyApp"みたいな)。これで以下のファイルが生成されます。 MyApp.javaGWTのクライアントサイドのクラスで、通常のGWTのアプリケーションと同じ様にコーディングします。

ページの生成

以下のコマンドを実行して、GWTの画面を提供するためのページ(gsp)を作成します。
grails create-gwt-page main/index.gsp sample.MyApp
このとき対応するControllerが存在しない場合には、作成するかどうか聞かれるので、作成します。MainControllerとgrails-app/views/main/index.gspが作成されます。

実行

この状態でRPCを使わないアプリケーションは実行することができます。 "grails run-app"でサーバを起動しておきます。GWTのHostedブラウザを使用する場合には
grails run-gwt-client
を実行して、コントローラの一覧からMainControllerを選択するとGWTアプリケーションが表示されます。 Grails Pluginでは、"grails compile"か"grails run-app"のタイミングでGWTのクラスもコンパイルされるので、Hostedブラウザではなく一般のブラウザでアクセスすることもできます。

RPC

GrailsのサービスでGWTのRPCを使ってみます。 まず、Grailsのサービスを作ります。
grails create-service MyService
grails-app/serviceにMyServiceができるので、これを以下のように編集します。
import org.codehaus.groovy.grails.plugins.gwt.annotation.CollectionTypeArg
class MyService {
	static expose = [ 'gwt:sample.client' ]

	@CollectionTypeArg(String)
	List listBooks() {
		…
	}
}
  • exposeでこのサービスを使用するクライアントのパッケージを指定します。
  • listBooksが実際のサービスで、結果としてStringのリストを返します(リストの中身はCollectionTypeArgアノテーションで指定します)。
サービスを作成すると、以下のクライアント側で使用するサービスインタフェースが自動で生成されます。 MyService.javaを見ると、CollectionTypeArgアノテーションの指定が、GWTgwt.typeArgsアノテーションに反映されていることがわかります。 クライアント側(src/java/sample/MyClient.java)でRPCを利用するコードを追加します。
public class MyClient implements EntryPoint {
    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        // 初期化処理

    	MyServiceAsync myService = (MyServiceAsync) GWT.create(MyService.class);
    	ServiceDefTarget endpoint = (ServiceDefTarget) myService;

    	// URLは"rpc"をつけたものになる
    	String moduleRelativeURL = GWT.getModuleBaseURL() + "rpc";
    	endpoint.setServiceEntryPoint(moduleRelativeURL);

    	myService.listBooks(new AsyncCallback(){
		public void onFailure(Throwable caught) {
			// 失敗した場合の処理
		}
		public void onSuccess(Object result) {
			// 成功した場合の処理
		}
    	});
    	
        // 初期化処理の続き ...
    }
通常のGWTを使う場合と変わらないです。ただ、GrailsのドメインクラスはそのままRPCでやり取りすることはできない(みたい)なのでどうしたものか。。Groovyっぽく解決できればと思うのですが、下手なことをするよりはJSONを使った方がよいかもしれません。