2008/01/19

BlazeDS + Seasar2(S2Flex) + Flex(Cairngorm)


AdobeからBlazeDS(現時点ではβだけど)が公開されたので、これを機にSeasar2と連携させてみた。
今まではS2FlexのGatewayを使っていたけど、そこんとこをBlazeDS任せにする。
BlazeDSはFlex Data Servicesとベースは一緒なので、S2Factory for FDS2を試したところ、S2Containerにサービスのインスタンスを登録するのはそのままイケた。

手順としてはこんな感じ。

1. BlazeDS一式をダウンロード、展開。

BlazeDS
http://labs.adobe.com/technologies/blazeds/

2008年1月19日現在はblazeds_b1_121307.zipというアーカイブファイルで提供されている。
この中にはBlazeDSの空コンテキストやサンプルアプリケーションコンテキスト等が含まれている。

2. BlazeDSアプリケーションの設定。

展開後のblazeds_b1_121307\tomcat\webapps\blazeds に空コンテキストがあるので、それをベースにBlazeDSアプリケーションを構築していく。

2.1. web.xmlの設定。
blazeds\WEB-INF\web.xmlにs2filterの設定を追加する。

<filter>
<filter-name>s2filter</filter-name>
<filter-class>org.seasar.framework.container.filter.S2ContainerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>s2filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2.2. Flexコンパイルオプション -context-root, -services の設定。

FlexBuilderでFlexコンパイラのオプションを設定する。
FDSと違って、このコンパイルオプションを指定しないとRemoteObjectの呼び出しで失敗してしまった。

blazedsというコンテキストであれば下記のように指定する。

-context-root /blazeds -services=C:\blazeds\WEB-INF\flex\services-config.xml

BlazeDSではなく、FDS(LCDS)を使う場合はWeb層コンパイラにコンテキスト名を渡す必要がそもそもないのでこのようなコンパイルオプションは不要っぽい。

BlazeDSではWeb層コンパイラや他いろいろが提供されていないので、上記のオプションが必要。
FlexBuilderコンパイラはflex-config.xmlは使用しないので、コンパイルオプションにload-configオプションの指定をする。

http://livedocs.adobe.com/flex/2_jp/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001490.html

外部ファイル内部でcontext-root, servicesを記述して、コンパイラにその外部ファイルをロードさせる形でもOK。
その場合のコンパイルオプションはこんな感じにした。

-load-config+=C:\blazeds\WEB-INF\flex\flex-config-ext.xml

load-configのところが += ってしてあるのは、FlexBuilderが内包するデフォルト設定(flex-config.xml)に追加する形とするため。

flex-config-ext.xml

<flex-config>
<compiler>
<context-root>/blazeds</context-root>
<services>services-config.xml</services>
</compiler>

<metadata>
<title>blazeds with Seasar2</title>
<description>blazeds with S2 application</description>
<publisher>infy2c</publisher>
<creator>infy2c</creator>
<language>JA</language>
</metadata>
</flex-config>

3. S2Factory for FDS2, S2Flex2, S2Container2 2.4をダウンロード、展開。

S2Factory for FDS2
http://akabana.sandbox.seasar.org/ja/products/fds/

前提条件に
・Flex Data Services2
・S2Flex2
・S2Container2 2.4
が挙げられているけど、今回はBlazeDSを使うので、Flex Data Services2はいらない。

S2Factory for FDS2を通してFlexクライアントのリクエストに応えるインスタンスを生成する。

Flex2開発ガイドのファクトリメカニズムの使用を参照。
ファクトリメカニズムの使用
http://www.adobe.com/livedocs/flex/201_jp/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=ent_services_config_097_26.html

3.1. FlexFactoryの設定。

C:\blazeds\WEB-INF\flex\services-config.xml にFlexFactoryの設定を追加する。

<factories>
<factory id="s2" class="org.seasar.flex2.rpc.remoting.service.fds2.factory.Seasar2Factory" />
</factories>

3.2. RemoteObjectの設定。

C:\blazeds\WEB-INF\flex\remoting-config.xml にRemoteObjectのdestinationを追加する。

下記のような記述をRemoteObjectの数分だけ必要になる。
factoryには3.1. で指定したs2を使う。

<destination id="hogeService">
<properties>
<factory>s2</factory>
</properties>
</destination>

なお、クライアント側はFDSを使っていたときのものでOK。
私はCairngormを使用しているので、下記のような感じになる。

ServiceLocatorとBusinessDelegateを例に挙げておく。
コマンドクラスをresponderに指定して、BusinessDelegateのメソッドを呼んでください。
Services.xml(ServiceLocator)

<?xml version="1.0" encoding="utf-8"?>
<cairngorm:ServiceLocator
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:cairngorm="com.adobe.cairngorm.business.*">
<mx:RemoteObject
id="hogeService"
destination="hogeService"
result="event.token.resultHandler(event);"
fault="event.token.faultHandler(event);">
</mx:RemoteObject>
</cairngorm:ServiceLocator>

hogeDelegate.as(BusinessDelegate)

package hoge {
import com.adobe.cairngorm.business.ServiceLocator;

import mx.rpc.AbstractService;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;

public class hogeDelegate {
private var responder:IResponder;
private var service:AbstractService;

public function hogeDelegate(responder:IResponder) {
this.service = ServiceLocator.getInstance().getService("hogeService");
this.responder = responder;
}

public function hoge():void {
var token:AsyncToken = service.hoge();
token.resultHandler = responder.result;
token.faultHandler = responder.fault;
}
}

かなり手抜きだけど以上。