メイン

ColdSpring アーカイブ

2008年04月22日

ColdSpring

ColdSpring を活用してみよう。
すでに ColdSpring の機能である、“DI”というものについての記述は、たくさんあるので、どのように使うかを見ていく。
よい題材が思いつかなかったので、Common.cfc で生成していた商品リストを「強引に」ColdSpring でやってみよう。
ColdSpring.xml に下記のように記述する。

 <bean id="itemArrayBean" class="shopping.model.ItemArrayBean">
  <property name="itemArray">
   <list>
    <map>
     <entry key="name"><value>光学式マウス</value></entry>
     <entry key="price"><value>2600</value></entry>
    </map>
    <map>
     <entry key="name"><value>ボール式マウス</value></entry>
     <entry key="price"><value>1100</value></entry>
    </map>
    <map>
     <entry key="name"><value>レーザー式マウス</value></entry>
     <entry key="price"><value>4800</value></entry>
    </map>
   </list>
  </property>
 </bean>

ここで注意しなければならないのは、Model-Gule は、ColdSpring.xml などのファイルを、OSのデフォルトエンコーディングを前提に
読み込んでいるらしく、Windows で動作させる場合は、Shift_JIS で保存しなければ、文字化けしてしまった。

 <?xml version="1.0" encoding="UTF-8"?>

としても、だめだった。他のOSでは試していないので、あくまで、推測である。
自動で判別してくれるとか、先頭行をチェックしてから読み込むということは、してくれないようである。

shopping.model.ItemArrayBean は、商品リストデータを保持するコンポーネント。
Java でいうところの、Bean ということになる。ColdSpring でも、この Bean という単語を採用している。
デフォルトでは、リクエストごとに、インスタンスが生成されているようだ。
固定値を保持するような Bean は、アプリケーションで1インスタンスでいいのだから、何かしら、やり方があるのだろうか。
singleton とかの記述もマニュアルにあるし、できそうな雰囲気もあるが、試していない。

では、実際に、これを利用するためには、どうすればよいのか。
コントローラーでは、非常に簡単に利用できる。
getModelGlue().getBean("itemArrayBean") これだけで、取得できてしまうのである。
Controller.cfc にある、onRequestStart 関数に
<cfset variables.itemArrayBean = getModelGlue().getBean("itemArrayBean") /> とすれば、Controller.cfc 上では、いつでも、利用可能になる。

また、あたかも、AutoWire のように、

 <cffunction name="setItemArrayBean" access="public" returnType="void" output="false">
  <cfargument name="itemArrayBean" type="any">
  <cfset variables.itemArrayBean = arguments.itemArrayBean />
 </cffunction>

としてやるだけでも、取得できてしまう。
「あたかも、AutoWire のように」としたのは、ColdSpring.xml の bean タグに、AutoWire の設定することなく、
setter 関数が処理されたためにこのような表現をした。コントローラーは、本当に特別なもののようだ。
AutoWire については、また、後日、読み解いてみたい。

2008年04月23日

ColdSpring で Bean へデータを渡す

では、コントローラーではないコンポーネントに ColdSpring の Bean を渡すには、どうすればよいのか。
ロジックの、CartProcess.cfc に itemArrayBean を渡す方法を考えてみよう。

bean タグは、子要素に、constructor-arg と、property を持つことができる。
constructor-arg は、コンストラクタの引数として渡すためのタグ。
property は、setter 関数で渡すためのタグとなっている。


 <bean id="shopping" class="shopping.model.CartProcess">
  <constructor-arg name="itemAB">
   <ref bean="itemArrayBean" />
  </constructor-arg>
 </bean>

と ColdSpring.xml に記述してやることによって、CartProcess.cfc の初期化の際に、引数で自動的に渡してくれるのである。
初期化の関数は、デフォルトで、init になっているようで、


 <cffunction name="init" returntype="any" access="public" output="false">
  <cfargument name="itemAB" required="true">
  <cfset variables.itemArray = arguments.itemAB.getItemArray() />
  <cfreturn this />
 </cffunction>

という記述を、CartProcess.cfc にしてやると、CartProcess.cfc 上で、いつでも商品リストデータが利用可能になる。

一方、

  <constructor-arg name="itemAB">
   <ref bean="itemArrayBean" />
  </constructor-arg>

を、

  <property name="itemAB">
   <ref bean="itemArrayBean" />
  </property>

とすると、自動的に、CartProcess.cfc にある、setItemAB という関数を探して itemArrayBean を渡してくれるのである。

再び、サンプルアプリケーションを作ってみた。
できることは同じであるが、ColdSpring を利用して、コントローラーへ、自動的に、データを渡している。

サンプルColdSpring

2008年04月24日

AutoWire

さて、たびたび出てきた AutoWire とは、何か。
ColdSpring のドキュメントによると、

The term "autowire" refers to the ability of the ColdSpring beanFactory to automatically wire dependent objects together without necessarily having to define those dependencies in the xml bean definitions.

とある。
簡単に言うと・・・、説明は止めておこう。実際に、どのように動くのかを見た方がわかりやすい。
検索すれば、AutoWire も、いっぱい出てくる。もちろん、ColdSpring での情報は少ないが。

前回、

 <bean id="shopping" class="shopping.model.CartProcess">
  <property name="itemAB">
   <ref bean="itemArrayBean" />
  </property>
 </bean>

このような記述をした。
ColdSpring.xml の Bean は、基本的にリクエストごとに、初期化される。
shopping.model.CartProcess を初期化する際に、setItemAB 関数を探して、引数として、itemAB という名前で、itemArrayBean を
渡して処理しなさいということであった。

AutoWire を使えば、この記述が以下のように簡単になる。

 <bean id="shopping" class="shopping.model.CartProcess" autowire="byName" />

autowire="byName" をautowire="byType" とすることもできる。
要するに、Bean を受け取りたい側(この場合は、CartProcess.cfc)で、setter 関数を記述さえすれば、取得できるわけである。

byName と、byType は、どう違うのか。名前と型なわけで、全く違うわけだが、byName であれは、setItemAB と名前で探すのに対し、

<bean id="shopping" class="shopping.model.CartProcess" autowire="byType" />


<cfargument name="itemArrayBean" type="shopping.model.ItemArrayBean" />

byType の場合は、setter 関数の名前は set で始まっていればよく、引数の受取の型指定が一致しているものを探すわけである。

同じ型で複数の Bean を作りたい場合には、byName にすることになるだろう。
byTypeの方は、すでに setter 関数があって、名前が重複してしまった場合などに利用することになるだろう。

基本的には、好みで決めればいいのだろう。byType の方が、好みだ。

2008年04月30日

ColdSpring によるAOP(Aspect Oriented Programming)

ColdSpring のDIコンテナとセットで、AOPというものが解説されることがある。
これも、たくさん記述があるので、それを読んでみても、何がどう便利でどう簡単なのかが、ピンと来ない。
というわけで、実践。

ColdSpring AOP Tutorial - Part Oneとか、ColdSpring ドキュメントや、ColdSpring のサンプルからちょっとコードを拝借。

ログを書き出す機能を、これまでのアプリケーションに、AOP手法で実装してみる。

とりあえず、どれぐらい簡単なのかを確認するために、ログ機能を利用するための諸設定などは、すでに行われているものとすれば、実に、簡単である。

やろうとしていることは、shopping.model.CartProcess コンポーネントの関数を実行するたびに、ログを書き出すようにしたい。
ということで、それには、ColdSpring.xml の中の、

 <bean id="shopping" class="shopping.model.CartProcess" autowire="byType" />

これを


 <bean id="cartProcessTarget" class="shopping.model.CartProcess" autowire="byType" />
 
 <bean id="shopping" class="coldspring.aop.framework.ProxyFactoryBean">
  <property name="target">
   <ref bean="cartProcessTarget" />
  </property>
  <property name="interceptorNames">
   <list>
    <value>loggingAdvisor</value>
   </list>
  </property>
 </bean>

とするだけである。
が、実際、簡単なんだと思えるまで、結構時間がかかった。

2段階でコンポーネントのインスタンスを取得していることになる。
こうして得られる shopping インスタンスは、coldspring.aop.framework.ProxyFactoryBean ではなく、
あたかも shopping.model.CartProcess そのもののように、扱うことができる。

そして、shopping 上の関数を利用すると、ログ書き出しが機能してしまうのである。
既存の shopping.model.CartProcess のコードを書き換えることなく、機能追加を実装できてしまった。

いやいや、ログを取る場合は、もっと細かいレベルで、見たいのではないかと。
例えば、shopping.model.CartProcess の関数は、「カートに商品を入れる」というものであり、
このログ機能が処理されるタイミングは、shopping.model.CartProcess の関数が実行される前、後、その両方、
そして、エラーが発生した場合で設定できる。
既存の関数にログをはき出す機能を付けても、それでは、たいした効果は期待できない。

AOPとは、再利用可能でシンプルな見やすいプログラムを作ることが目的の一つになっている。
例えば、データベースに対して、引数で与えたSQL文を発行するだけというような、再利用できる低レベルでの関数であれば、
その関数の前後などで、ログを書き出すことは、意味を持ってくるのだろう。

また、ログに限らず、AOPは、トランザクション処理や、キャッシュ処理、権限チェック処理などが利用例としてあげられており、どのようなものを実装するかで、意義は変わってくるのだろう。

2008年05月01日

AOPの実装

では、どのようにAOPを実装するのかを見ていく。

前回のログを書き出すコードとして拝借したファイルは、LogginAroundAdvice.cfc と LoggingService.cfc の2つ。
LoggingService.cfc は、ログを書き出すだけのコンポーネント。
LogginAroundAdvice.cfc は、ログの機能を追加しようとしている関数に対して、どういうタイミングでログを書き出すかを
指定(Advice)するためのコンポーネント。

Advice という用語が出てきた。これが実にわかりにくい。
今でも、はっきりわかっていない。おぼろげな認識では、
“どういう機能(ログ書き出し)をどのタイミング(前、後、前後、エラー時)で提供”するかということだろうか。
そして、Advisor というものもある。その Advice を“どういうものに付け加えるかを指定”するとでも言うのだろうか。
ドキュメントの英文を読んでも、ピンと来ないし、困ったものだ。


 <bean id="loggingService" class="shopping.model.aop.component.LoggingService" />
 
 <bean id="loggingAdvice" class="shopping.model.aop.aspects.LoggingAroundAdvice">
  <property name="loggingService">
   <ref bean="loggingService">
  </property>
 </bean>
 
 <bean id="loggingAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">
  <property name="advice">
   <ref bean="loggingAdvice" />
  </property>
  <property name="mappedNames">
   <value>*</value>
  </property>
 </bean>

ColdSpring.xml で、このように設定する。
loggingService という Bean を設定し、その機能を AroundAdvice する loggingAdvice を設定。
任意の関数名で処理を織り込む(Weave)loggingAdvisor を設定。

これにより、ログ機能(shopping.model.aop.component.LoggingService)をAOPで利用するための準備が整う。

前回の

 <bean id="shopping" class="coldspring.aop.framework.ProxyFactoryBean">
  <property name="target">
   <ref bean="cartProcessTarget" />
  </property>
  <property name="interceptorNames">
   <list>
    <value>loggingAdvisor</value>
   </list>
  </property>
 </bean>

で、bean id="shopping" に引数 interceptorNames で渡している loggingAdvisor が上記の設定でできるのである。

サンプルアプリケーション

2008年05月13日

Transfer のトランザクション処理

サンプルアプリケーションは、データベースのトランザクション処理ができていない。
こんなアプリケーションが許されるわけはないので、トランザクションを実装しなければならない。
トランザクションはどのように実装するのか。

やり方としては、コンポーネント内の指定した関数を丸ごとトランザクション処理するというイメージになる。
shopping.model.CartProcess の transfer.TransferFactory を AutoWire したタイミングで、transfer.TransferFactory から transfer.com.sql.transaction.Transaction を取得する。

<cffunction name="setOrmService" access="public" returntype="void" output="false">
 <cfargument name="ormService" type="transfer.TransferFactory" required="true">
 <cfset variables.transfer = arguments.ormService.getTransfer() />
 <cfset variables.transaction = arguments.ormService.getTransaction() />
</cffunction>

その Transaction を利用して、

 <cfset transaction.execute(component, methodName, [arguments]) />

と、直接的に関数をトランザクション指定で起動することもできる。
直接指定の場合は、その関数を利用するときに、上記の記述で利用することになる。

また、AOPのように記述して、関数を指定することで、指定した関数が丸ごとトランザクション処理されるようだ。
この記述の場合は、事前に行っておくことで、その関数を通常のように利用した場合でも、トランザクション処理されることになる。

<cffunction name="setOrmService" access="public" returntype="void" output="false">
 <cfargument name="ormService" type="transfer.TransferFactory" required="true">
 <cfset variables.transfer = arguments.ormService.getTransfer() />
 <cfset variables.transaction = arguments.ormService.getTransaction() />
 <cfset variables.transaction.advise(this, insertItem) />
</cffunction>

さらに、

 <cfset arguments.transaction.advise(this, "^save") />

と、正規表現で一括してトランザクション処理指定もできる。
トランザクションで処理したい関数を save で始まる関数名にしておけば、簡単に一括指定できる。

2008年05月26日

Model-Glue の初期設定

ここらで、基本的なところに戻って、ColdSpring.xml の先頭にある、
<bean id="modelGlueConfiguration" class="ModelGlue.unity.framework.ModelGlueConfiguration">
を見ていこう。

ここでは、Model-Glue の各種設定項目を、DIコンテナである ColdSprng で設定しているということになる。
設定できる項目は、以下の通り。

続きを読む "Model-Glue の初期設定" »

2008年05月27日

XMLの設定ファイルの豆知識

ところでいくつかあるXMLの設定ファイルで、どうするのかなぁと感じていたことがある。
特定のディレクトリを絶対パスで指定したい場合に、配置するサーバーの状態によっては、ディレクトリ名を変えないといけないこともあるだろう。そうしたときに、XML内の該当箇所を全て置き換えていかないといけないのかなぁ。とちょっと不便に思っていた。

ところが、ここのソースを見て解決した。
要は、ColdFusion レベルの手法ではなく、XMLレベルの手法で解決すればいいのだ。

続きを読む "XMLの設定ファイルの豆知識" »

2008年06月03日

Observer を Inject する

Google Groups に参考になるスレッドが上がってた。
addXXXObserver(component), where to call? is singleton required?
そこからのリンクMy Take on Transfer ORM Event Model - BeforeCreate Example
Observer の登録の仕方だ。これを参考にすると、すっきりした。

続きを読む "Observer を Inject する" »

2008年06月04日

ちょっと楽になるかな?ツール

もともと、無精なものだから、どうにも Transfer の Generated Methods の入力が煩わしい。
多少でも楽になればと思い、ちょっとツールを作ってみた。
これを使えば、
developing_04.gif
こういう風に、一覧で利用できる関数を表示してくれる。

続きを読む "ちょっと楽になるかな?ツール" »

2008年06月06日

ColdSpring の Remote Facades

ColdSpring のドキュメントに Remote Facades という項目がある。
これも確か、デザインパターンで見たような気がする。
便利なサイトがあったので、参考にさせてもらった。ありがたい。
なるほどなるほど。
実際の実装にはここを参考にさせてもらった。

で、とりあえず、http://localhost/shopping/model/ItemArrayBean.cfc?method=getItemArray にアクセス。

コンポーネント [[リポジトリ]]\shopping\www\model\ItemArrayBean.cfc のメソッド 'getItemArray' はリモートでアクセスできません。

cffunction の access 属性が public なのだから当然。

続きを読む "ColdSpring の Remote Facades" »

2008年09月22日

Railo 浮上

以前のエントリーで、Railo に見事撃沈された我がサンプルアプリケーション。
その Railo が正式リリースされたと聞いたので、もう一度、動作確認してみた。

続きを読む "Railo 浮上" »

2008年11月05日

CF Frameworks Explorer ってなんぞ?

CFEclipse を導入する際に、ずっと気になっていたけど、

cfframeworks01.gif

こんな風だし、

cfframeworks02.gif

右クリックで、“構成”を選択すると、

cfframeworks03.gif

こんな警告出るし、

こんなウィンドウが表示されるだけで、なんなんだよ、これ。って感じで、放置していた CF Frameworks Explorer 。

でも、ここ の「08 CF Frameworks Explorer Introduction」を見て、一気に解決。

続きを読む "CF Frameworks Explorer ってなんぞ?" »

About ColdSpring

ブログ「気楽に行こう」のカテゴリ「ColdSpring」に投稿されたすべてのエントリーのアーカイブのページです。過去のものから新しいものへ順番に並んでいます。

前のカテゴリはColdFusionです。

次のカテゴリはModel-Glueです。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。