2008年9月4日木曜日

GWTとSpringの連携

GWTでサーバサイドロジックを呼び出すためには、用意されているRPC(Remote Procedure Call)の仕組みを利用する。

一方、近年のJavaによるWebアプリケーション開発では、ビジネスロジックのインスタンス管理は、何らかのDIコンテナに任せてしまうのが常套手段だ。個人的には長いことSpringを使っていることもあり、GWTのRPCをSpringのbeanに置き換えできないかを試してみることにした。
使用したのは下記のライブラリ。

GWT Server Library (GWT-SL)
http://gwt-widget.sourceforge.net/

GWTのRPCは特定のurlにマッピングされたServletとして動作するが、GWT-SLではurlとSpringのbeanをマッピングするモジュールを用意されており、それとSpringMVCのDispatcherServletと組み合わせてSpringのbeanを呼び出せるようになっている。
GWT-SLでRPCとして公開可能なbeanには、下記の3種類の戦略が用意されている。

  • 完全なるPOJO
  • GWT RPCのServiceインタフェースを実装したクラス
  • GWT RPCのServiceインタフェースを実装し、GWTSpringControllerを継承したクラス

POJOは公開されるRPCのインタフェースに関連がないクラスになるため、メソッドが増えると管理が難しそう。3番目の方法は古いバージョンのGWT-SLにおける手法(ただしパフォーマンスはよいとのこと)らしいので、2番目の方法を前提とした構築手順を下記に示す。

1. GWT-SLをダウンロードし、WEB-INF/lib配下に置く。
2. GWT-SLのServletを定義する。
下記の記述をweb.xmlに追記する。

<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.rpc</url-pattern>
</servlet-mapping>

※servlet-nameやurl-patternは特に限定されておらず、任意の値で設定できる。

3. Springの定義ファイルにマッピング情報を記述する。
Springの定義ファイルは、web.xmlで記述したServlet名によって変わり、WEB-INF/[サーブレット名]-servlet.xmlとなる。

<bean id="urlMapping" class="org.gwtwidgets.server.spring.GWTHandler">
<property name="mapping">
<map>
<entry key="/test.rpc" value-ref="testServiceImpl" />
</map>
</property>
</bean>

いちいちbean名とurlの記述を書かなければならないのがめんどくさいと思ったが、よくよく考えたら何でもかんでもRPCとして公開されたら大変なのでこれは仕方のないことだ。

4. GWTモジュールから呼び出す。

TestServiceAsync service = GWT.create(TestService.class);
ServiceDefTarget target = ((ServiceDefTarget) service);
target.setServiceEntryPoint(GWT.getModuleBaseURL() + "test.rpc");
service.hoge();

これでSpringのbean呼び出しが可能である。
ただこのままでは、GWTのhostedモードでRPCの呼び出しができない。モジュールをリコンパイルしてデプロイし直すのでは恐ろしく時間がかかりすぎるため、次回はhostedモードでSpring RPCを呼び出す方法を書く。

2008年9月1日月曜日

GWTでBigDecimal

一度エントリ投稿し始めたら、あとはそこそこ続くもの。

今回はGWTでBigDecimalを使う方法。
Google先生に軽く聞いた限りでは見つからなかったのだが、よくよく調べてみると見つかった。

まず、現時点でのGWT(v1.5.2)では、BigDecimalはサポートされていない。BigDecimalをGWTで利用するためには、gwt-mathという外部ライブラリを利用する必要がある。

gwt-math
http://code.google.com/p/gwt-math/

使い方は至って簡単。公式サイトにも書いてあるが、下記の通りだ。
  • 利用するモジュールのgwt.xmlに以下のinheritエレメントを追加する。
    • <inherits name="com.googlecode.gwt.math.Math"/>
  • gwt-math-[version].jarをダウンロードし、クラスパスに追加する。
  • もしRPCのパラメータやreturnでBigDecimalを利用する場合は、さらにgwt-math-server-[version].jarもダウンロードし、クラスパスに追加する。
これだけだ。
RPCのシリアライズ通信やjsコンパイラの仕組みがよくわかっていないので、どうやって拡張を実現しているのかわからないが、他に特にややこしい設定など必要とせず、これだけで問題ないようだ。
(jsに関しては、java.math.BigDecimalをエミュレーションするJavaScriptを用意しているように見える)