今回から,SCAのプログラミング・モデルについて具体的に解説していきます。

非常に柔軟なアセンブリ・モデル

 SCAの世界を理解しようと思ったとき,最初に読むべき資料は「Assembly Model Specification」です。現在は,2007年3月21日に発表されたV1.00が最新です。SCAの仕様書は複数に分かれているのですが,厚さからいってもこのアセンブリ・モデルの仕様がその中心です。仕様書といっても図も多用されていて比較的読み易いもので,SCAにおける作成物である“Composite”とその構成要素についての仕様が定められています。

 「一体,SCAって何を作るための仕様?」という疑問に答えてくれるのがこの仕様書なのですが,読み易いとはいえ,そこは仕様書,頭から読み進めていくと途中で迷子になったりします。筆者も最初は,何度読んでも途中で?と思う部分がありました。読み進んでいくと同じ言葉の定義が何度も出てくるのです。

 しばらくして,これこそがSCAの特徴と気付きました。自由度の高い設計にするために使用する(一般的な意味の)コンポーネントの各所で必要な設定(例えば,後述のReference)をできるようにしてあるのです。そしてこれらの設定は,それを利用する側でもできるようになっています。つまり利用する側で必要に応じてオーバーライド(上書き)して使用するようになっています。

 SCAの仕様を読みながら「どうしてまた,Referenceが出てくるの?」というような場合には,このことを思い出していただければと思います。

Componentを組み合わせたComposite(コンポジット)

 SCAで何かを作って動かそうと思ったときに,その何かはCompositeという形態をとります。Compositeとは,複合,合成と言った意味です。SOAでの開発成果物は,複数のサービスを組み合わせたものになるため,それがSCAでのCompositeになるわけです。

 では,このCompositeには何が含まれているのでしょう? 図3-1は,第2回でも紹介したサンプル・コード「Abcサービス」(リスト1)のCompositeの例です。Compositeの中にいくつかのComponentが含まれているのがわかります。このComponentが実装を表しています。Compositeは通常,Component,Service,Reference,Propertyを含みます(AbcCompositeでは,Composite外に対する参照が必要無いため,CompositeレベルでのReferenceは定義していません)。

図3-1●サンプル「Abcサービス」のCompositeの例
図3-1●サンプル「Abcサービス」のCompositeの例


/* Java によるサービス・コンポーネントの実装例 */
/*       Abcサービスの実装コード       */

package abc;

import org.osoa.sca.annotations.Service;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Property;

@Service(AbcService.class)
public class AbcServiceImpl implements AbcService {

  @Reference
  protected PriceService priceService;

  @Property
  protected float discountRate;

  public int getDiscountPrice(int price) {
    return priceService.getDiscountPrice(price,discountRate);
  }
}
リスト1●JavaでSCAのコンポーネントを記述した例(前回のリスト1と同じ)

 上記の図3-1は,XMLでの定義をわかりやすく表現したもので,実体はリスト2のXML文書になります。SCA V1.0の仕様では,このファイルは,XXX.Compositeという名前で表現すると定義されています※1

※1 筆者がテストに使用しているオープンソースのSCA Runtime「Apache Tuscany M2」では,ファイル名がXXX.SCDLとなっています。


<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
           name="AbcComposite">

   <service name="AbcService">
      <interface.java interface="abc.AbcService"/>
      <reference>AbcServiceComponent</reference>
   </service>

   <component name="AbcServiceComponent">
      <implementation.java class="abc.AbcServiceImpl"/>
      <property name="discountRate">0.75</property>
      <reference name="priceService">PriceServiceComponent
      </reference>
   </component>

   <component name="PriceServiceComponent">
      <implementation.java class="abc.PriceServiceImpl"/>
   </component>

</composite>
リスト2●AbcCompositeの定義XML

実装をインスタンス化するComponent(コンポーネント)

 このComponentがSCAの最小単位ということができます。そして,Componentは各言語で書かれたImplementation(実装)を指し示します。実装の開発者は,ビジネス・ロジックを記述すると同時に,そのコードを動かすために必要な情報を記述します。

 言語仕様としてIntrospectionをサポートしているJavaの場合,必要な情報はアノテーションによって自動的に生成されます。ここで必要な情報とは,「そのコードが何をReference(参照)しなければいけないか」「Serviceとしてどのようなinterfaceを外部に公開するか」「どのようなプロトコルで公開するか」「どんなProperty(外部変数)を使用しているか」──といった情報です。これらの情報を基にSCAは,実装をインスタンス化します。

 現在,Componentを実装可能なものとして定義されているものは,以下の通りです。これらは現在仕様として公開されているものというだけで,今後拡張される可能性があります。すでにPHP対応のコミュニティも立ち上がっていますし,今後,COBOLサポートの可能性もあります。

  • Java
  • C++
  • BPEL
  • Spring
  • Composite

 上から四つの実装言語については,Implementationに関する独立した仕様書が提供されています。リスト3は,サンプル「Abcサービス」のCompositeの定義XMLから一部抜き出したものです。


<component name="AbcServiceComponent">
  <implementation.java class="abc.AbcServiceImpl"/>
  <property name="discountRate">0.75</property>
  <reference name="priceService">PriceServiceComponent</reference>
</component>
リスト3●AbcServiceComponentの定義部分

 リスト3の2行目が実装コードを指し示している部分です。ここでは,Javaを使用して,“abc.AbcServiceImpl”というクラスで実装していることを宣言しています。参考までに,ほかの言語やフレームワークを利用する場合,Implementationの定義は下記のようになります。

C++ <implementation.cpp library="XXX" header="YYY" scope="ZZZ" />
BPEL <implementation.bpel process="XXX"/>
Spring <implementation.spring location="XXX"/>

 リスト3の3行目のpropertyは,実装の中で使用している変数discountRateに0.75という値を与えています。このAbcサービスでは,割引率をこのPropertyで渡しています。

 4行目のreferenceは,この実装が動作するためには,priceServiceという参照を与える必要があることを表しています。priceServiceもまたComponentです(上記の図3-1参照)。

 ここでのComponent定義は,実装コード“abc.AbcServiceImpl”(リスト1参照)のintrospectionの結果をオーバーライドしている形になっていることにご注意ください。

Compositeは再帰的

 先に挙げたComponentに実装可能な言語やフレームワークの中に,Compositeが挙げられていることを奇妙に感じた方もいらっしゃるかもしれません。これは,Compositeの中の一つのComponentの実装にまたCompositeが使えるということです。

 実は,SCAは,このような再帰的な実装が可能になっています。つまり,一度作成したCompositeは,他のCompositeの中のComponent実装の一つとして利用可能ということです。これはRecursive Model(再帰的モデル)と呼ばれているSCAの大きな特徴の一つです。

 Compositeを実装として使用する場合には以下のように記述します。

<implementation.composite name="XXX" />

 これはサービス指向の考え方と親和性の高いアーキテクチャになっています(図3-2)。

図3-2●Recursive Model(再帰的モデル)でのプログラム開発
図3-2●Recursive Model(再帰的モデル)でのプログラム開発

 組み合わせの階層の上位のサービスが,よりビジネスに近い抽象的なものと考えられます。言葉を変えると“粒度”(Granularity)が粗いということができます。

 再帰性を利用すると最初にざっくりとしたサービスを上流から定義していくというトップダウン・アプローチも可能です。細かい実装は,もっと粒度の細かいCompositeに任せればいいのです。逆からのアプローチもありです。それだけでは,粒度が細かすぎて使い難いCompositeを束ねてもっと粒度の粗いものにしていくというボトムアップ・アプローチもできます。

 どちらのアプローチを採用したにしても最終的にできあがるものは,SCA仕様に基づいたCompositeであり,末端の実装に至るまで統一された,検証可能なXML定義によって表現されます。

 次回は,今回に引き続き「SCAのプログラミング・モデルとは」(中編)です。Componentと外部との関係を定める“Service”と“Reference”について説明していきます。

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