では、いよいよServiceMix本体の話になってきます(デモのダウンロードはServiceMix (1) JBIとServiceMix から)。
まずServiceMixそのものの作りを簡単に説明しておきましょう。ServiceMixはSpring上で動きます。現状ではSpringにしか対応していない部分もありますが、比較的簡単に他のDIコンテナ上で動かすことも出来るはずです(ServiceMix1はGeronimo上で動くようにしている人がいました)。
はじめに書いた通りJBIではコンテナにBCやSEをデプロイします。そのためのデプロイメント・ディスクリプタは非常に煩雑になっています。あとで説明しますが、ServiceMixはSpringを利用してBC、SEをデプロイするので、デプロイを単純にしており、さらにBCやSEをSpringのBeanと同じようにDIの対象することができます。
このためにServiceMix2の定義ファイルに利用されているのがxbeanです。xbeanはGeronimoプロジェクトからの派生なのですが、設定ファイルを便利に書くためのライブラリで、Springもサポートしています。"Spring in Action" のCraig Walls氏がブログに書いたSpring Simplified with XBeanにまとまっていますが、Springの記述を単純にするための1つの解決策として注目されています。
上記のエントリからの抜粋ですが、
<beans>
<bean id="knight"
class="....KnightOfTheRoundTable">
<property name="moniker">
<value>Bedivere</value>
</property>
<property name="quest">
<ref bean="quest"/>
</property>
</bean>
</beans>
と書くところを
<beans>
<knight id="knight" moniker="Bedivere"
xmlns="http://springinaction.com/schemas/knight">
<myQuest><quest/></myQuest>
</knight>
<beans>
って感じで書けちゃいます。つまり特定のクラスをBeanとして登録するのに専用のタグが使えるようになっているのです。
コンポーネント・コンポジットをXMLファイルで表現しようとすると、エクテンション・ポイントの形式を明示するために専用のXMLの要素(タグ名)や属性を追加したくなります。TapestryのHiveMindではいきなり要素を追加してしまうのですが、そうするとXMLのバリデーションが利用できなくなります。xbeanがスマートなのは名前空間によってXMLのバリデーションを生かしたままで良い点です。この手法は流行ると思います。
ServiceMixではJBIのサービス名やエンドポイント名などを指定するために利用しています。まじめにSpringで記述していると非常に見にくくなってしまうのですが、xbeanのおかげでかなり直感的にすることができるのです。
では、servicemix.xmlの見方を説明します。まずサンプルを見てください。
<beans xmlns="http://xbean.org/schemas/spring/1.0" xmlns:spring="http://xbean.org/schemas/spring/1.0" xmlns:sm="http://servicemix.org/config/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xbean.org/schemas/spring/1.0 spring-beans.xsd http://servicemix.org/config/1.0 servicemix.xsd" xmlns:foo="http://servicemix.org/demo/"> ...[1] <sm:container spring:id="jbi" useMBeanServer="false" createMBeanServer="false" dumpStats="true" statsInterval="10"> ...[2] <sm:activationSpecs> <sm:activationSpec id="hoge" service="foo:hoge" destinationService="foo:bar"> ...[3] <sm:component> ...[4] <bean xmlns="http://xbean.org/schemas/spring/1.0" class="foo.Hoge" /> ...[5] </sm:component> </sm:activationSpec> <sm:activationSpec ... <sm:activationSpecs> </sm:container> <beans>
要素beans[1]はxbeanのためにXMLスキーマを設定しています。属性xmlns:fooは、あとで出てきますがサービスのための名前空間fooを定義しています。
内側の要素sm:container[2]がJBIコンテナになります。JBIはJMXでの管理を行うことができるので、その設定を行います。今回のデモは1台の端末に2つのServiceMixを立ち上げる都合上、ポート番号がぶつかってしまうために属性useMBeanServerをfalseにしています(本当はポート番号をかえてあげるべきですが)。
ServiceMixは、このJBIコンテナだけをSpring上にデプロイしているだけです。ですからSpring内包しているわけではなく、BCやSEをJBIコンテナにデプロイするためだけにDIコンテナをうまくつかっています。そのため、他のDIコンテナへの移行も単純に行える訳です。
要素sm:activationSpec[3]がJBIのコンポーネント、つまりBCやSEを"アクティベート"するために使われています。ここの説明がややこしいのですが、JBIのコンポーネントはロジックを書くだけではなく、JBI上で機能するために様々な情報を登録する必要性があります。具体的にはサービス名やエンドポイント名をNMRに登録するのですが、これをアクティベートと呼びます(ここらへんはWSDL2の話なので、なんとなく名前を登録するんだ程度の理解で良いです)。
ServiceMixではJBIへのデプロイを単純にするためにアクティベート処理を行ってくれるコンポーネントをアダプタとして用意し、そのコンポーネントにビジネスロジックをインジェクトするように設計されています。こうすることでアクティベート処理とビジネスロジックを完全に切り離しているのです。ここらへんもDIをうまく利用しているなぁと感じます。
属性id(もしくはcomponentName)が、実コンポーネントを呼び出す名前です。次の属性serviceがJBI上でのサービス名になります。JBIでは名前空間を付けることでサービス名を定義します。Javaのパッケージ名と同じですが、こうすることで複数のサービスを名前をかぶることなく利用できるようになるわけです。なおエンドポイント名は指定しなければサービス名と同じになります。最後の要素destinationServiceが、次にルーティングするサービスを示します。
その内側の要素sm:component[4]が、これまたアダプタになっています。JBIではメッセージ交換するために様々なコンポーネントを利用します。それらを全部扱うのは大変なのでベースクラスを提供し、これを継承する形でロジックを記述します。そのベースクラスに、いろいろなものをインジェクトする必要性があるので、それを行うためのアダプタになります。
そして要素bean[5]が、ようやく普通のSpringの設定になります。属性xmlnsを指定することで、その内側については名前空間の指定が不要になります。
では、ここからは実際の各コンポーネントを見ていきましょう、、と思ったのですが、長くなったのでまた次回ということで(w。
