サンプル解説
それでは、Calculatorサンプルを利用してTuscany上で作成するSCAアプリケーションについて説明しよう。
Calculatorは1つのコンポジットからなるSCAアセンブリであり、図にすると以下のようになる。
コンポジットCalculatorComposite内に全てのコンポーネントが格納されており、コンポーネントCalculatorServiceComponentがその他の全コンポーネントを参照しているのがお分かりだろう。この構造をSCDLで記述したものが「calculator/src/main/resources/META-INF/sca/default.scdl」である。以下、ファイル内にコメントを追加したものを示す。
<!-- コンポジットの定義。名前はCalculatorComposite -->
<composite name="CalculatorComposite" xmlns="http://www.osoa.org/xmlns/sca/1.0">
<!-- コンポジット外部に公開するサービス「CalculatorService」-->
<service name="CalculatorService">
<!-- Javaインタフェースをサービスのインタフェースとして使用 -->
<interface.java interface="calculator.CalculatorService"/>
<!-- コンポーネント「CalculatorServiceComponent」を参照 -->
<reference>CalculatorServiceComponent</reference>
</service>
<!-- コンポーネント「CalculatorServiceComponent」 -->
<component name="CalculatorServiceComponent">
<!-- Javaの実装クラスの指定 -->
<implementation.java class="calculator.CalculatorServiceImpl"/>
<!-- 他のコンポーネントを参照している -->
<reference name="addService">AddServiceComponent</reference>
<reference name="subtractService">SubtractServiceComponent</reference>
<reference name="multiplyService">MultiplyServiceComponent</reference>
<reference name="divideService">DivideServiceComponent</reference>
</component>
<!-- コンポーネント「AddServiceComponent」-->
<component name="AddServiceComponent">
<implementation.java class="calculator.AddServiceImpl"/>
</component>
<!-- コンポーネント「SubtractServiceComponent」-->
<component name="SubtractServiceComponent">
<implementation.java class="calculator.SubtractServiceImpl"/>
</component>
<!-- コンポーネント「MultiplyServiceComponent」-->
<component name="MultiplyServiceComponent">
<implementation.java class="calculator.MultiplyServiceImpl"/>
</component>
<!-- コンポーネント「DivideServiceComponent」-->
<component name="DivideServiceComponent">
<implementation.java class="calculator.DivideServiceImpl"/>
</component>
</composite>
では、このサンプルの核となるコンポーネントCalculatorServiceComponentの実装クラス「calculator.CalculatorServiceImpl」をざっと見てみよう。
以下のコードは、クラスcalculator.CalculatorServiceImplの中から注意すべき部分を抜き出したものだ。
@Scope("MODULE") ・・・(1)
public class CalculatorServiceImpl implements CalculatorService ・・・(2)
{
private AddService addService;
・・・略・・・
@Reference ・・・(3)
public void setAddService(AddService addService) {
this.addService = addService;
}
・・・略・・・
public double add(double n1, double n2) {
return addService.add(n1, n2); ・・・(4)
}
・・・略・・・
}
括弧書きの数字を付けた部分は、以下のようになっている。
(1) コンポーネントのインスタンスが共有されるスコープを指定している。現在のTuscanyにおけるJava APIは、SCA仕様バージョン0.95を基にしているため"MODULE"というスコープ名が使用されている。バージョン1.0では"COMPOSITE"となり、コンポジット内で1つのコンポーネントインスタンスが共有されるという設定になる。ちなみに、スコープには他に"STATELESS"(共有されない)、"REQUEST"(1つのリクエスト内で共有される)、"CONVERSATION"(対話中継続される)がある
(2) CalculatorServiceというインタフェースを実装していることに注目。Tuscanyは、指定されたインプリメンテーションが実装しているインタフェースを、自動的にコンポーネントのサービスインタフェースとする。したがって、CalculatorServiceComponentが提供するサービスのインタフェースはCalculatorServiceである
(3) SCDLで定義していたaddServiceという名前のリファレンスが、インプリメンテーション上ではSetter Injectionを利用したコードとなり、他のサービスへの参照を取得できている。その際利用するのは@Referenceというアノテーションであり、このアノテーションが付加されたフィールド、コンストラクタ、Setterメソッドが依存性注入の対象となる
(4) AddServiceのメソッドを利用し、数値の合計を求めている
大体の雰囲気はつかめただろう。重要なのは(2)と(3)であり、SCDLと実装コードの接点になっている部分でもあるので、よく理解していただきたい。