澤出 達郎(さわいで たつろう)
日本アイ・ビー・エム ソフトウェア事業 ICP コンサルティング I/Tスペシャリスト

 前回は,SCAにおける業務ロジックの実装を担当するComponentと最終的な入れ物であるCompositeについて述べました。今回は,関係を定義する機能であるServiceとReferenceについて,Javaでの実装を例に解説します。

サービスは他者に依存する

 あるサービスが単体で成立していることは,おそらくまれなことです。成立しているとすれば,たぶん非常に粒度が細かいものでしょう。

 多くの場合は,外部の機能を必要とします。これは他者に依存するということですが,特定のサービス提供者に依存する必要はありません。必要とするインタフェースさえあっていれば,相手は誰でも構わないのです。

 SCAにおけるComponentは,Reference(参照)をうまく分離することにより,できるだけ参照先と関係無く動くことができるようになっています。この分離のアーキテクチャは,サービスを公開する場合も同様です。Service(公開インタフェース)の定義が分離されているため公開に関する機能はビジネス・ロジックとは無関係になっています。

始まりはImplementationから

 SCAのService/Referenceには,複数の場所に定義が存在する多重構造になっています。このあたりは,ちょっとわかり難い部分ですが,Implementation(実装コード)から順番に見ていくとその構造がよくわかります。

 まずは,Referenceから解説します。ソースコード(リスト1)の(1)の部分がImplementationにおけるReferenceの定義になります。これがReferenceの基点になります。

リスト1●Javaによるサービス・コンポーネントの実装例。「Abcサービス」のComponentの実装コード
リスト1●Javaによるサービス・コンポーネントの実装例。「Abcサービス」のComponentの実装コード

 Javaに詳しい方でしたら「priceServiceのinstanceはどうなってるの?」と思われるかもしれません。そのinstance化の部分が,SCAのRuntimeの役割になります。つまり,priceServiceの実体は,SCA Runtimeが何らかの方法で与えるのです。それは,ローカルのJava VMの中にあるかもしれませんし,リモートと関係する場合もあります。

 リスト1(1)の@Referenceは,以下のように書くことも可能です(リスト2)。こちらのほうがPOJOとしては自然に見えると思います。この場合のSCA Runtimeの役割は,このsetter(setAddService)を呼び出してinstanceを与えることになります。


private PriceService priceService;

@Reference
public void setAddService(PriceService priceService) {
  this.priceService = priceService;
}
リスト2●Setterに設定した@Reference@

 これらの@Referenceの動作をSCA仕様書において“Reference Injection”(参照の注入)と呼んでいる場合もあります。確かにDI(Dependency Injection)的な観点でみると“Injection”(注入)を行っていると言えます。Runtimeが実際にどのようなinstanceを注入するかは,以下のComponentまたはCompositeにおけるReferenceの定義が関係してきます。

ComponentレベルでのReference

 Componentの定義の中にReferenceを書くことができます。これは“Component Reference”とも言われ,Composite内での参照を定義します。このComponent Referenceからの接続先としては,他のComponentの“Component Service”,もしくはComposite外への参照を行う“Composite Reference”になります。リスト3は,第3回にも登場したAbcサービスのCompositeのXML定義です。

リスト3●AbcCompositeの定義XML
リスト3●AbcCompositeの定義XML

 リスト3(1)のReferenceは,priceServiceという名前の参照に対してPriceServiceComponentの参照を与えることを宣言しています。(2)のComponent「PriceServiceComponent」がその参照先であり,それはJavaで実装されていることがわかります。

CompositeレベルでのReference

 このレベルのReferenceは,Composite外への参照を表します。ComponentレベルでのReferenceを解決するために,Composite外のリソースを使用する場合に利用します。

 このReferenceの定義によって,ComponentレベルのReferenceのつなぎ先を決めることができます。例えば,リスト3のAbcサービスの定義は,図で表すと図1のように表されますが,参照先(点線枠)を図2のように外部のWebサービスに切り替えることができます。

図1●サンプル「Abcサービス」のコンポジット図
図1●サンプル「Abcサービス」のコンポジット図

図2●外部Webサービスを参照するように変更
図2●外部Webサービスを参照するように変更

 その場合は,Compositeの定義XML上は,リスト4の用に変更します。点線枠が変更になった部分です(リスト3と比較すると違いがわかります)。

リスト4●変更されたAbcCompositeの定義XML
リスト4●変更されたAbcCompositeの定義XML

 (1)でAbcServiceComponentからの参照を「PriceService」に変更し,(2)でComposite Referenceである「PriceService」を追加していることがわかります。このReferenceは,interface定義をWSDLで行い,binding定義をWebサービスで行うように定義されています*1。ここで利用しているWSDLは,Webサービス「PriceService」を提供している,リモート・アクセスが可能な外部のCompositeから提供されたものです。

Componentを公開する定義“Service”

 リスト4のAbcCompositeでは,「AbcService」という名前で外部へサービスが公開されています((3)の部分)。公開のプロトコルは,ローカルのJavaです。

 公開されるサービスのinterfaceは,javaインタフェース「abc.AbcService」で定義されています。このことは,リスト1の(2)の@Service(AbcService.class)部分で宣言されています。Serviceによって公開されるComponentは,Referenceで指定されている「AbcServiceComponent」になります*2。このサービスがローカルのみのアクセスとなるのは,ImplementationのソースコードにもService定義にもリモート・アクセス可能な定義がないからです。

 次回は,サンプル「Abcサービス」のソースコードを見ながら,Abcサービスの作り方を解説します。リモート呼び出し可能なサービス定義の方法やinterface,bindingなど,まだ説明していない重要なポイントも含みます。お楽しみに。

─ 注釈 ─

*1 ここでの例は,執筆時点でのSCA RuntimeであるApache Tuscany M2での動作することを重視しているため,SCA V1.0の構文とは若干異なっています。SCA V1.0では,promoteという属性でComponentとReferenceの関係を指定できるようになっています。

例:<reference name="PriceService" promote="AbcServiceComponent/PriceService">

*2 *1と同様の理由で,この定義もSCA V1.0の構文とは若干異なっています。例では,serviceの中でrefereceを定義してComponentを指定していますが,SCA V1.0では,promoteという属性で公開したいcomponentを指定できるようになっています。

例:<service name="AbcService" promote="AbcServiceComponent">