ColdSpring のドキュメントに Remote Facades という項目がある。
これも確か、デザインパターンで見たような気がする。
便利なサイトがあったので、参考にさせてもらった。ありがたい。
なるほどなるほど。
実際の実装にはここを参考にさせてもらった。
で、とりあえず、http://localhost/shopping/model/ItemArrayBean.cfc?method=getItemArray にアクセス。
コンポーネント [[リポジトリ]]\shopping\www\model\ItemArrayBean.cfc のメソッド 'getItemArray' はリモートでアクセスできません。
cffunction の access 属性が public なのだから当然。
次に、単純に、access 属性を remote にしただけの場合。
要素 TRANSFER は、 として参照されているタイプ class [Ljava.lang.String; の Java オブジェクト内で未定義です
よく見る ColdFusion のエラー。Model-Glue が Transfer を利用できるようにしてくれているわけだから、Model-Glue を経由しない、
コンポーネントへの直接リモートアクセスでは、だめなわけか。
それにしても、この単純和訳は、なんとかならんものだろうか。
shopping.model.ItemArrayBean.cfc の getItemArray 関数をリモートから利用できるようにしてみる。
まず、リモートへの Facade(と言っていいのかな?)となる shopping.model.ItemService.cfc を作成する。
<cfcomponent displayname="ItemService" output="false">
<cfprocessingdirective pageencoding="UTF-8" />
<cffunction name="init" access="public">
<cfargument name="itemArrayBean" type="any" required="true" />
<cfset variables.itemArrayBean = arguments.itemArrayBean />
</cffunction>
<cffunction name="getItemList" access="remote">
<cfreturn variables.itemArrayBean.getItemArray() />
</cffunction>
</cfcomponent>
次に ColdSpring.xml に、以下のように追加。
<bean id="itemService" class="&topOfPackage;.model.ItemService">
<constructor-arg name="itemArrayBean"><ref bean="itemArrayBean" /></constructor-arg>
</bean>
<bean id="itemService_remote" class="coldspring.aop.framework.RemoteFactoryBean">
<property name="target">
<ref bean="itemService" />
</property>
<property name="beanFactoryScope">
<value>application</value>
</property>
<property name="beanFactoryName">
<value>beanFactory</value>
</property>
<property name="serviceName">
<value>rItemService</value>
</property>
<property name="relativePath">
<value>/&topOfPackage;/model/remote</value>
</property>
<property name="remoteMethodNames">
<value>*</value>
</property>
</bean>
bean id="itemService" はいいと思うけど、ここで肝心なのが、bean id="itemService_remote"。
Remote Facades の対象とする Bean を target で指定。
BeanFactory がどこのスコープに入っているかを beanFactoryScope で指定。
BeanFactory の名前をどのように命名しているかを beanFactoryName で指定。
serviceName は、この名前のコンポーネントが、relativePath に生成される。実際にリモートで利用するためには、この生成されたコンポーネントを指定する。
remoteMethodNames は、利用できる関数を制限、指定できる。
さて、Model-Glue 経由じゃないと、いろいろと不都合があるので、BeanFactory を取得するタイミングが問題である。
Controller の一番最初に駆動される関数 getItemList に、以下のコードを追加してみた。
ColdSpring の BeanFactory が どこかのスコープに入ってないと行けないらしい。Andy Jarrett 氏は、Application にしている。
それが一番妥当で簡単だろう。
<cfscript>
if (NOT IsDefined("application.beanFactory")) {
application.beanFactory = getModelGlue().getBeanFactory();
application.beanFactory.getBean('itemService_remote');
}
</cfscript>
ただ、元々、BeanFactory は、Model-Glue が管理しているので、これを Application スコープに入れてしまうのっていいのだろうか。
何かうまい方法あるのかなぁ。
こうして、http://localhost/shopping/model/remote/rItemService.cfc?method=getItemArray で、リモート利用できる。
http://localhost/shopping/model/remote/rItemService.cfc?wsdl で、Web サービスも可能ということか。