トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

dm-service-registry

Chapter 6. サービス・レジストリ(The Service Registry)


OSGiサービス・レジストリは公開されたJavaインターフェースのセットに基づいてBundleがObjectを共有レジストリへ公開することを可能にします。
公開されたサービスは同じくレジストリ内に付属のサービス・プロパティーを持っています。

Spring Dynamic ModulesはSpring beanをOSGiサービスとして使用可能にし、またサービス・レジストリに含まれているサービスの参照を定義する為のSpringのOSGi namespace(Appendix H, Spring Dynamic Modules Schema?を参照)を提供します。
そのnamespace要素(エレメント)は他のトップレベルのnamespace(例えばSpring beans namespaceなど)のネストの内側から、又はトップレベルのOSGiエレメントから使用されます。

下記の例はSpring beansエレメント内からOSGi namespaceを使用していることを表します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"                               (1)
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:osgi="http://www.springframework.org/schema/osgi"                               (2)
   xsi:schemaLocation="http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans.xsd                      (3)
       http://www.springframework.org/schema/osgi  
       http://www.springframework.org/schema/osgi/spring-osgi.xsd">

    <osgi:service id="simpleServiceOsgi" ref="simpleService"                             (4)
      interface="org.xyz.MyService" />
</beans>

(1) Spring Framework beans schemaをデフォルトのnamespaceとして使用する。
(2) Spring Dynamic Modules schemaをインポートし、プレフィクスを設定しています。(ここでは「osgi」)
(3) Spring beans schema version 2.5がインポートされるように指定。
(4) Spring Dynamic Modulesエレメントが定義されたプレフィクスを使用しています(ここでは「osgi」)。

OSGi namespaceをトップレベルのnamespaceと使用するには下記のように設定します。

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans                                                                             (1)
   xmlns="http://www.springframework.org/schema/osgi"                                    (2)
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:beans="http://www.springframework.org/schema/beans"                             (3)
   xsi:schemaLocation="http://www.springframework.org/schema/osgi  
       http://www.springframework.org/schema/osgi/spring-osgi.xsd
       http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans.xsd">                    (4)

    <service id="simpleServiceOsgi" ref="simpleService"                                  (5)
       interface="org.xyz.MyService" />

</beans:beans>                                                                           (1)

(1) 「beans」ルート・エレメントのプレフィクスはSpring Framework beans schemaのプレフィクスです。
(2) Spring Dynamic Modulesのスキーマがデフォルトnamespaceとして使用されます。
(3) Spring Framework beansスキーマがインポートされ、プレフィクスによってnamespaceに関連付けられています。
(4) Spring beans schema version 2.5がインポートされています。
(5) プレフィクス無しでSpring Dynamic Modulesのエレメントが使用できます。


専用の配置ファイルをOSGi関連の全ての宣言に使用する為にセクション5.1「Bundle format and Manifest headers」の推奨に従う場合、トップレベルのnamespaceにOSGi namespaceを使用することは特に便利です。

  6.1. OSGiサービスとしてのSpring beanの公開(Exporting a Spring bean as an OSGi service)


「service」エレメントはOSGiサービスとして公開されているbeanを定義します。
少なくとも、公開されるbeanとサービスの型をあらわすインターフェースを指定する必要があります。

例えば、下記の設定では、

<service ref="beanToPublish" interface="com.xyz.MessageService"/>

「beanToPublish」の名前でcom.xyz.MessageServiceのインターフェースを持つbeanを公開することをあらわします。
公開されたサービスは「org.springframework.osgi.bean.name」内に登録された名前(この場合は「beanToPublish」)のサービス・プロパティーを持ちます。

「service」エレメントで定義されたbeanは、org.osgi.framework.ServiceRegistration型であり、またOSGiサービス・レジストリに公開されたServiceRegistrationオブジェクトです。
beanに名前(id)を与えることによって、必要であればServiceRegistrationオブジェクトを他のオブジェクトにインジェクションすることもできます。

例えば、

<service id="myServiceRegistration" ref="beanToPublish"
     interface="com.xyz.MessageService"/>

名前のついたbeanを公開する他の方法として、サービス・レジストリに公開されたbeanはサービス・エレメント内の匿名インナーbeanとしても定義されています。

例えば、トップレベルのnamespaceが「beans」の場合の記述方法では、

<osgi:service interface="com.xyz.MessageService">
  <bean class="SomeClass">
     ...
  </bean>
</osgi:service>

公開されているbeanが「org.osgi.framework.ServiceFactory」インターフェースを実装している場合、OSGi Service Platformコア仕様のsection 5.6「ServiceFactory」契約が尊重されます。

このOSGi APIを実装する事の他の手段として、Spring Dynamic Modulesでは新しいbean scopeである「bundle scope」が導入されました。
「bundle scope」のスコープを持ったbeanがOSGiサービスとして公開された場合、1つのbeanインスタンスがOSGiサービス・レジストリを通してそれを参照している各クライアントbundle(公開されているサービスを使用しているbundle)毎に作成されます。
サービスを利用している側のbundleが停止されると、それ用に作成されて関連付けられていたインスタンスは破棄されます。

bundle scopeのbeanを定義するには単にbean設定のscope属性に設定するだけです。

<osgi:service ref="beanToBeExported" interface="com.xyz.MessageService"/>

<bean id="beanToBeExported" scope="bundle" class="com.xyz.MessageServiceImpl"/>

6.1.1. 公開されているサービスの公開サービス・インターフェース・セットのコントロール(Controlling the set of advertised service interfaces for an exported service)


OSGiサービス・プラットフォーム・コア仕様では「service interface」という用語を「サービスの公開しているメソッドの仕様をあらわすもの」と定義しています。

単位的にそれはJavaでのinterfaceをあらわしますが、しかし仕様はサービスobjectをclass名で登録することもサポートしています。
よって、「サービス」という語句は「class」とも「interface」とも解釈できます。

登録され公開されるサービスのインターフェースを定義する方法にはいくつかの選択肢があります。
もっとも単純なメカニズムは、上記で示したように、完全修飾のinterface名を「interface」識別子に使うことです。
複数のネストしたインターフェースの下でサービスを登録する場合、「interfaces」要素が「interface」属性の代わりに使用できます。

<osgi:service ref="beanToBeExported">
  <osgi:interfaces>
     <value>com.xyz.MessageService</value>
     <value>com.xyz.MarkerInterface</value>
  </osgi:interfaces>
</osgi:service>

「interface属性」と「interfaces要素」を同時に指定することはできません。どちらか一方だけを指定することができます。



(訳注:ここは6.1.1.1.節の横にある囲み記事です)

可視性の階層構造(Hierarchy visibility)

「auto-export」を使用している場合、サービスを公開しているbundleに見えている型だけが登録されることに注意するべきです。
例えば、もし「auto-export="interfaces"」を使っている場合、親interfaceの「SI」が公開されているbundleのclasspathに乗っていない場合、「SI」はサーポートされるサービス・インターフェースとしては公開されません。

同様に、もしサービスクラスがその親からSIを透過的に実装(implements)している場合、設定されているbundleがそのインターフェースをインポートしていなければ、そのクラスは公開されたサービスにとってはunknownとなります。

これには率直に違和感を覚えるかもしれませんが、それは実際には「bundle製作者にクラス視界およびパスに対するコントロールを与える」というOSGiの最も強力な特徴のうちの1つです。

詳細な説明はFAQを参照してください。

(訳注:囲み記事ここまで)



6.1.1.1. 公開インターフェースの実行時決定(Detecting the advertised interfaces at runtime)


「auto-export」属性を使えばobjectのclass階層とインターフェースを解析し、サービス・インターフェースの明示的な宣言をしないで済みます。

「auto-export」属性は以下の4つのうちの1つの値をとります。

  • disabled : デフォルトの値。サービスインターフェースの自動検出は行われず、「interface」属性か「interfaces」要素が代わりに必要になります。
  • interfaces : 公開されるbeanのJavaインターフェースタイプでサービスが登録されます。
  • class-hierarchy : 公開されるbeanの実装型(implementation type)と親typeでサービスが登録されます。
  • all-classes : 公開されるbeanの実装型と親typeに加え、継承している全てのインターフェースでサービスが登録されます。

「auto-export」と「interface(s)」は互いに排他的ではありません。必要とされるのであれば公表されるインターフェースによる最適な粒度コントロールの為に両方は同時に指定することもできます。
しかしながら、前掲のオプションで十分な場合がほとんどだと思われます。

例えば、サポートする全てのインターフェースをもって自動的に登録するには以下のように設定します。

<service ref="beanToBeExported" auto-export="interfaces"/>

実装されているインターフェースは以下のようであるとします。

public interface SuperInterface {}

public interface SubInterface extends SuperInterface {}

すると、「SubInterface」をサポートするとして登録されたそのサービスは、OSGi内で「SuperInterface」をサポートする検索では該当しないものとして扱われます。
この為、これは「interfaces」要素か「auto-export="interfaces"」のいずれかの使用により、明示的に登録されたサービスによってサポートされる全てのインターフェースを公開する事のベスト・プラクティスです。

6.1.2. 公開されるサービスのプロパティーのコントロール(Controlling the set of advertised properties for an exported service)


先に説明されているように、公開されるサービスは常に、beanが公開された名前で設定されたorg.springframework.osgi.bean.nameサービスプロパティーとともに登録されます。
追加のサービスプロパティーは入れ子になった「service-properties」要素によって設定することが可能です。
「service-properties」要素はサービスによって公開されるプロパティーの「key」と「value」の複数のペアを含みます。

「key」はStringの値で、「value」はOSGi Filterによって認識可能な型である必要があります。
どのようにプロパティーの値がfilterの記述にマッチされるのかについての詳細はOSGiサービス・プラットフォーム・コア仕様のSection 5.5を参照してください。

「service-properties」要素はSpring beans namespaceからの1つ以上の入れ子エントリーから成る必要があります。

例を示すと、

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface">
  <service-properties>
    <beans:entry key="myOtherKey" value="aStringValue"/>
    <beans:entry key="aThirdKey" value-ref="beanToExposeAsProperty"/>
  </service-properties>
</service>

Spring Dynamic Modulesのロードマップは登録されたサービスのプロパティーとしてOSGi Configuration Administration serviceに登録されたプロパティーを公開する為のサポートを含んでいます。
詳細はAppendix F, Roadmap?を参照してください。

6.1.3. 「depends-on」属性(The depends-on attribute)


Springはサービス・エレメントの明示的な依存性を管理します。例えばサービスとして公開されるbeanが公開される前にコンストラクトされ、設定されることを確実にする、などの為です。
もしサービスが他のコンポーネント(他のサービス・エレメントを含む)に対して暗黙的な依存性を持っていると、それはそのサービスが公開される前に完全に初期化が終わっていなくてはなりません。
「depends-on」オプション属性はそれらの依存性を提供する為に使用されます。

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface"
     depends-on="myOtherComponent"/>

6.1.4. コンテキスト・クラス・ローダー属性(The context-class-loader attribute)


OSGiサービス・プラットフォーム・コア仕様(最新バージョンの4.1が策定中の現段階)では、どのような型やリソースがあるオペレーションがサービス・レジストリ上のサービスで実行された時点でcontext class loaderを通して可視かを規定していません。
例えばあるサービスがcontext class loaderに対してある仮定を期待しているライブラリを使用するなどという場面で、Spring Dynamic Modulesはサービス実行中のcontext class loaderの明示的なコントロールを可能にします。
それはサービス・エレメントの「context-class-loader」オプション属性を使用することによって設定できます。

「context-class-loader」に使用可能な値は、「unmanaged(デフォルト)」と「service-provider」です。
「service-pprovider」が設定されているとき、Spring Dynamic Modulesはサービスを公開したbundleのclasspathにある全てのリソースがcontext class loaderから見えることを保障します。

「context-class-loader」属性値を「service-provider」に設定したとき、そのサービス・オブジェクトはclass loaderを扱う為にproxyで置き換えられます。
サービスが実装クラスを公開している場合、GCLIBライブラリが必要になります。

6.1.5. ランキング属性(The ranking attribute)


あるサービスをサービス・レジストリに登録するとき、「service ranking」を付加することもできます。(OSGiサービス・プラットフォーム・コア仕様のSeciton 5.2.5を参照)

Bundleがサービス・レジストリ内からサービスを検索したときに条件に合致するサービスが複数ヒットした場合、ランキングが最も高いサービスが返されます。

デフォルトのランキング値はゼロです。登録するサービスにランキングをつける場合は、「ranking」オプション属性を設定します。

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface"
  ranking="9"/>

6.1.6. 「service」要素の属性(service element attribute)


今までのまとめとして、下記のテーブルは属性の名前と取り有る値とその簡単な説明です。

Table 6.1. OSGi <service> attributes
属性名 説明
interface 完全修飾class名(FQN)(例:java.lang.Thread) 公開されるオブジェクトの完全修飾class名
ref 他のbeanの名前 サービス・レジストリからサービスとして公開されるbeanの名前によるリファレンス
context-class-loader 「unmanaged」「service-provider」 公開されたサービスの中で動作中にcontext class loaderがどのように振舞うかを設定します。デフォルトは「unmanaged」で、context class loaderに対して特別な操作は行われません。「service-provider」が設定されるとcontext class loaderは公開されたサービスのbundleのclass pathにあるリソースが見えるように操作されます。
auto-export 「disabled」「interfaces」「class-hierarchy」「all-classes」 Springが自動的にサービス・インターフェースの構造をコントロールできるようにします。デフォルトでこの機能は「disabled(無効)」に設定されています。「interfaces」を設定すると公開されているサービスの全てのJavaインターフェースが自動的に公開されます。「class-hierarchy」が設定されると公開されているサービスのclass階層にある全てのJava classが公開されます。「all-class」が設定されると全てのJavaインターフェースとclassが公開されます。
ranking integerの値 サービスのサービス・ランキングを指定します。デフォルトの値は0です。

6.1.7. サービスの登録/登録解除ライフサイクル(Service registration and unregistration lifecycle)


「service」要素で定義されたサービスはアプリケーション・コンテキストが最初に作成されたときにOSGiサービス・レジストリに登録されます。
そしてbundleがstopされアプリケーション・コンテキストが破棄されたときに自動的に登録解除されます。

依存性が解決できないためにサービスが登録解除されたときに(又は登録されたときに)何か独自の動作を追加したい場合、入れ子になった「registration-listener」要素を定義することによりregistration listener beanを通してそれを可能にします。

registration listenerの宣言はトップレベルのbean定義に「ref」属性を使うことでも、匿名のlistener beanをインラインで定義することによっても可能です。

例を示すと、

<service ref="beanToBeExported" interface="SomeInterface">
  <registration-listener ref="myListener"                                                (1)
    registration-method="serviceRegistered"                                              (2)
    unregistration-method="serviceUnregistered"/>                                        (2)
  <registration-listener
     registration-method="register">                                                     (3)
     <bean class="SomeListenerClass"/>                                                   (4)
  </registration-listener>
</service>

(1) トップレベルのbean定義で参照を定義することによるlistener beanの設定。
(2) registration時とunregistration時のメソッドの定義。
(3) registration時のリスナー・メソッドだけの定義。
(4) 入れ子にしたlistener beanの定義。

オプションの「registration-method」属性と「unregistration-method」属性は登録時や登録解除時に実行されるメソッドの名前を設定します。
登録時や登録解除時に呼び出されるcallbackメソッドは以下のどちらかのシグネチャと一致している必要があります。

public void anyMethodName(ServiceType serviceInstance, Map serviceProperties);

public void anyMethodName(ServiceType serviceInstance, Dictionary serviceProperties);

「ServiceType」は他の公開されたサービスと互換性のあるサービス・インターフェースも使用できます。

登録時のcallbackはサービスがスタートアップ時に最初に登録されたとき、またはその後に再登録されるときに実行されます。
登録解除時のcallbackはその理由の如何にかかわらず、サービスの登録解除プロセス時に実行されます。(例えば含まれるbundleが停止するときなど)

Spring-DMは宣言されている「ServiceType」引数型を使用し、それと互換性のあるサービスが登録/登録解除されたときにのみ実行されます。

「serviceProperties」は登録/登録解除されるサービスの全てのプロパティーを保持するMapを表します。
OSGi仕様との互換性を保つ為、この引数は必要であればjava.util.Dictionaryへキャストすることもできます。

6.1.7.1. 「OsgiServiceRegistrationListener」インターフェースの利用(Using OsgiServiceRegistrationListener interface)


我々が思いとどまっている間、Spring-DMのインターフェース「org.springframework.osgi.service.exporter.OsgiServiceRegistrationListener」を「registration-method」や「unregistration-method」の代わりに実装することもできます。
しかしながら、OsgiServiceRegistrationListenerを実装することによってそのコードは「Spring-DM aware(Spring-DMを使用した・依存した)」コードになってしまいます。(これはPOJO哲学(POJO主義)に反する事です。)

リスナーの為にOsgiServiceRegistrationListenerインターフェースを実装し、カスタムメソッドを宣言することもできます。
この場合、最初にSpring-DMインターフェースのメソッドが実行され、次にカスタムメソッドが呼ばれます。

  6.2. OSGiサービスへの参照の定義(Defining references to OSGi services)


Spring Dynamic Modules supportsはOSGiサービス・レジストリを通してアクセスするサービスを表すbeanの定義をサポートします。
この方法でOSGiサービスへの参照(references)はアプリケーションコンポーネントへインジェクションされます。
サービス検索(service lookup)はサポートに必要なサービス・インターフェース型の検索、それに加えてそれはレジストリ内に公開されているプロパティーと一致するもののオプショナルなフィルター設定に使用されます。

あるシナリオにおいて、アプリケーションからの検索条件全てにに該当するある1つのサービスがあります。
「reference」要素は要求する使用に該当する1つのサービスへの参照を定義します。
別のシナリオにおいては、特にOSGiの「ホワイトボード・パターン(whiteboard pattern)」を使用している場合、全ての該当するサービスへの複数の参照が要求されます。
Spring Dynamic Modulesはそれらの複数の参照をList、またはSetとして管理することをサポートします。

6.2.1. 特定のサービスへの参照(Referencing an individual service)


「reference」要素はサービス・レジストリ内のあるサービスへの参照を定義するのに使用されます。

与えられた条件に対して複数のサービスがマッチすることがあるので、結果得られるサービスは「BundleContext.getServiceReference」の呼び出し結果のサービスとなります。
この事は最も高いランキング(ranking)が付けられたサービスが返されるか、もしくはランキングが同じであった場合、サービスIDが最も小さいサービス(フレームワークによって最初に登録されたサービス)が返されることを意味します。(サービスの選択に関するアルゴリズムの更なる説明についてはOSGiサービス・プラットフォーム・コア仕様のSection 5を参照してください。)

6.2.1.1. インポートされたサービスの公開されたインターフェースのコントロール(Controlling the set of advertised interfaces for the imported service)


「interface」属性はマッチしたサービスが実装しているべきインターフェースを定義します。

例を挙げると、下記の設定は「messageService」beanを定義しており、それにはサービス・レジストリの中で「MessageService」インターフェースを実装しているサービスが選出されます。

<reference id="messageService" interface="com.xyz.MessageService"/>

下記のサービス定義のように複数のインターフェースを定義したい場合、「interface」属性の変わりに入れ子に「interfaces」要素を定義します。

<osgi:reference id="importedOsgiService">
  <osgi:interfaces>
     <value>com.xyz.MessageService</value>
     <value>com.xyz.MarkerInterface</value>
  </osgi:interfaces>
</osgi:reference>

「interface」属性と「interfaces」要素を同時に使うことはできません。一度にどちらか一方です。

「reference」要素によって宣言されたbeanは設定された、bundleから可視であるインターフェース全てを実装しています。(「意地汚いプロキシ(greedy proxying)」と呼ばれています。)
登録されたサービス・インターフェースがJavaの(interfaceではなく)class型を含んでいる場合、SpringのAOP実装による3種類の型がサポートされます。(Springのリファレンス・ガイドを参照)
端的に言えば、設定されたインターフェースがclass型だった場合(interfaceであっても)、CGLibライブラリが必須で、かつ「final」なメソッドはサポートされません。

6.2.1.2. 「filter」属性(The filter attribute)


オプショナルな「filter」属性はOSGiフィルター定義を表し、サービス・レジストリ検索の条件をフィルターします。

例えば、

<reference id="asyncMessageService" interface="com.xyz.MessageService"
  filter="(asynchronous-delivery=true)"/>

上記は「MessageService」インターフェースを公開しているOSGiサービスで、かつ「asynchronous-delivery」がtrueに設定されているサービスにだけマッチします。

6.2.1.3. 「bean-name」属性(The bean-name attribute)


「bean-name」属性は、「service」要素によって公開されたサービスによって自動的に付加される「bean-name」プロパティーにマッチするフィルター定義を表す便利なショートカットです。(Section 6.1, “Exporting a Spring bean as an OSGi service”を参照)

下記の公開/インポート定義において、

<bean id="(1)messageServiceBean" scope="bundle" class="com.xyz.MessageServiceImpl"/>
<!-- service exporter -->
<osgi:service id="messageServiceExporter" ref="(1)beanToBeExported" interface="com.xyz.MessageService"/>

<osgi:reference id="messageService" interface="com.xyz.MessageService"
   bean-name="(1)messageServiceBean"/>

(1)the name used with bean-name attribute

「MessageService」インターフェースを公開し、かつ「org.springframework.osgi.bean.name」が「defaultMessageService」に設定されているOSGiサービスがマッチします。
つまり、上記の設定は「Spring-DMが公開したbeanで、MessageServiceインターフェースを実装し、defaultMessageServiceという名前がついているもの」を意味します。


(訳注:ここは6.2.1.4.の横にある囲み記事です)

入れ子になった「reference」定義(Nested <reference> declarations)

Spring-DMが必須の依存性を検出する為に、全ての入れ子、もしくは内部の「reference」定義は自動生成された名前のトップレベルの「reference」定義に(自動的に)置き換えられます。

(訳注:囲み記事ここまで)



6.2.1.4. 「cardinality」属性(The cardinality attribute)


「cardinality」属性はマッチするサービスが常に必要かどうかを定義します。
「cardinality」値が「1..1」(デフォルト)である場合、該当のサービスが常に使用可能であることが求められます。
「cardinality」値が「0..1」である場合、該当のサービスが常に使用可能である必要はないことを表します。(詳細はSection 4.2.1.6を参照)

「cardinality」値が「1..1」である参照は「必須のサービス参照(mandatory service reference)」とも言われ、デフォルトでは、アプリケーション・コンテキストの生成は参照先が満足されるまで保留されます。

Note
同じbundleから公開されているサービスを必須サービス参照として宣言することはエラーになります。
このような設定はアプリケーション・コンテキスト生成時のデッドロックによるタイムアウトになります。

6.2.1.5. 「depends-on」属性(The depends-on attribute)


「depends-on」属性は指定されている名前のbeanが生成されるまでサービス参照がサービス・レジストリで参照されないことを設定します。

6.2.1.6. 「context-class-loader」属性(The context-class-loader attribute)


OSGiサービス・プラットフォーム・コア仕様(執筆時点での最新のバージョン4.1)では、サービス・レジストリからサービスが要求された時点でサービスのコンテキスト・クラス・ローダーからどの型やリソースが可視かという規定がされていません。

サービスがコンテキスト・クラス・ローダーを通して特定のライブラリを参照する為に、Spring Dynamic Modulesはサービス使用時の明示的なコンテキスト・クラス・ローダーのコントロール機能を提供します。
この機能はオプショナルな「context-class-loader」属性を「reference」要素に設定することによって行われます。

「context-class-loader」属性に使用可能な値は、

  • client -- サービス実行時に、コンテキスト・クラス・ローダーが呼び出し側bundleのclasspath上の型を可視であることを保障します。これはデフォルトの動作です。
  • service-provider -- サービス実行時に、コンテキスト・クラス・ローダーがサービス側で公開されているbundleのclasspath上の型を可視であることを保障します。
  • unmanaged -- サービス実行時にコンテキスト・クラス・ローダーの操作を行いません。


(訳注:ここは6.2.1.6.の横にある囲み記事です)

公開側と参照側のコンテキスト・クラス・ローダーの動作(context class loader management on the importer and exporter)

Spring-DMは公開側と参照側両方においてのコンテキスト・クラス・ローダー操作をサポートしています。
通常は、Spring-DMが公開側と参照側両方で作動している場合、片方でこの機能(コンテキスト・クラス・ローダー操作)が有効になっているべきです。
もし両側でこの機能が動作している場合、呼び出しチェインの最後のものが有効になります。
この事は「公開側の設定が有効であれば常に公開側の操作が参照側の設定を上書きする」ということです。

(訳注:囲み記事ここまで)



6.2.1.7. 「reference」要素の属性(reference element attributes)


まとめとして、下記の表は「reference」要素に使用可能な属性名、使用可能な値とその意味を列挙します。

Table 6.2. OSGi <reference> attributes
属性名 説明
interface 完全修飾class名(FQN)(例:java.lang.Thread) オブジェクトが公開しているべきclassの完全修飾名
filter OSGiフィルター定義(例:((asynchronous-delivery=true)) サービス・レジストリ内での検索条件に加えられるOSGiフィルター定義
bean-name 文字列 <service>要素で公開されているbeanに自動的に付加される「bean-name」プロパティーに対するマッチ条件。
context-class-loader 「client」「service-provider」「unmanaged」 サービス参照によりサービスが実行されたときにコンテキスト・クラス・ローダーに何が見えるかを設定する。デフォルトは「client」で、呼び出し側のbundleのclasspathが可視となります。別のオプションとして「service-provider」がありこれは公開側のbundleの、「unmanaged」はコンテキスト・クラス・ローダーに対して何も操作をしないことをそれぞれ表します。
cardinality 「0..1」「1..1」 参照先のサービスに要求されるcardinality(=濃度?)を設定します。設定を省略した場合、デフォルトが適用されます。「1..1」を設定した場合、参照先のサービスの存在が必須になります。(必須サービス参照)「0..1」を設定した場合、サービスが存在しないことも許容します(オプショナルなサービス参照)
timeout 正のlong値 オペレーションが要求されたときの合計待ち時間(単位:ミリ秒)。省略された場合、デフォルトの値がセットされます。

6.2.1.8. 参照とOSGiサービスの関係(reference and OSGi Service Dynamics)


「reference」要素で定義されたbeanはアプリケーション・コンテキストの生存期間を通じて変化しません(オブジェクト参照は固定的なものとして続きます)。
しかしながら、参照されたOSGiサービスはいつでも起動/終了する可能性があります。
必須サービス参照(cardinality属性が「1..1」のもの)の生成は、マッチするサービスの状態が「Available」になるまでブロックされます。
オプショナル・サービス参照(cardinality属性が「0..1」のもの)の場合、マッチするサービスの有無にかかわらず、参照は即座に生成されます。

サービス参照の実体のサービスが停止した場合、Spring Dynamic Modulesはその参照先のサービスを他のマッチするサービスで置き換えようと試みます。
アプリケーションは背後のサービスの状態変化を登録してあるlistenerを通じて通知されるかもしれません。
マッチするサービスがない場合、リファレンスは解決されていない状態になります。
解決されていない必須サービスは参照が解決されるまでの間それに依存している公開サービス(サービスbean)をサービス・レジストリに対して登録解除状態にします。
詳細についてはSection 6.5を参照してください。

未解決の参照に対してオペレーションが実行された場合(それがオプショナル参照か必須参照かに関わらず)、実行は参照が解決されるまでブロックされます。
「reference」要素のオプション属性の「timeout」値(ミリ秒)はそれに対してタイムアウト時間を設定することができます。
「timeout」値が設定され、かつマッチするサービスが時間までに解決されなければ、非チェック例外の「ServiceUnavailableException」が発生します。

6.2.1.9. マネージド・サービス参照の保持(Getting a hold of the managed service reference)


Spring-DMは自動的にマネージド(managed)OSGiサービスをサービス参照に変換できます。
すなわち、bean参照がインジェクションされることになっているプロパティーが「ServiceReference」型(参照にサポートされたサービス・インターフェースの代わりに)を持っていれば、サービス用のマネージドOSGi「ServiceReference」はサービス自体の代わりに注入されるでしょう。

public class BeanWithServiceReference {
	private ServiceReference serviceReference;
	private SomeService service;
			
	// getters/setters ommitted
}

<reference id="service" interface="com.xyz.SomeService"/>

<bean id="someBean" class="BeanWithServiceReference">
  <property name="serviceReference" ref="service"/>                                      (1)
  <property name="service" ref="service"/>                                               (2)
</bean>

(1) マネージド・サービスからServiceReferenceへの自動的な変換。
(2) マネージド・サービスが変換無しにインジェクションされる。

Note
インジェクションされた「ServiceReference」はSpring-DMによって管理され、参照されている実体のOSGiサービス・インスタンスが変化したときに同時に変化します。


(訳注:ここは6.2.2.の横にある囲み記事です)

自然な順序付け vs カスタム順序付け(Natural vs custom ordering)

Java collection APIは2つのインターフェースをオブジェクト順序付け方法の為に定義しています。「Comparable」と「Comparator」です。

前者はオブジェクトにより自然な順序付けを提供する為に実装されます。String、Long、Dateが「Comparable」インターフェースの実装の良い例です。

しかしながら、自然な順序付けとは異なる方法でソートする場合や、「Comparable」インターフェースを実装していないオブジェクトをソートする場合もあります。
そのような場合の為に「Comparator」インターフェースは用意されました。

これらについてのより詳しい説明は、Java Collectionチュートリアルの「Object ordering」の章を参照してください。

(訳注:囲み記事ここまで)



6.2.2. サービスのコレクションへの参照(Referencing a collection of services)


Sometimes an application needs access not simply to any service meeting some criteria, but to all services meeting some criteria. Spring-DM allows the matching services may be held in a List or Set (optionally sorted).

The difference between using a List and a Set to manage the collection is one of equality. Two or more services published in the registry (and with distinct service ids) may be "equal" to each other, depending on the implementation of equals used by the service implementations. Only one such service will be present in a set, whereas all services returned from the registry will be present in a list. For more details on collections, see this tutorial.

The set and list schema elements are used to define collections of services with set or list semantics respectively.

These elements support the attributes interface, filter, bean-name, cardinality, and context-class-loader, with the same semantics as for the reference element. The allowable values for the cardinality attribute are 0..N and 1..N.

A cardinality value of 0..n indicates that it is permissible for their to be no matching services. A cardinality value of 1..n indicates that at least one matching service is required at all times. Such a reference is considered a mandatory reference and any exported services from the same bundle (service defined beans) that depend on a mandatory reference will automatically be unregistered when the reference becomes unsatisfied, and reregistered when the reference becomes satisfied again.

The bean defined by a list element is of type java.util.List. The bean defined by a set element is of type java.util.Set.

The following example defines a bean of type List that will contain all registered services supporting the EventListener interface:

<list id="myEventListeners" interface="com.xyz.EventListener"/>

The members of the collection defined by the bean are managed dynamically by Spring. As matching services are registered and unregistered in the service registry, the collection membership will be kept up to date. Each member of the collection supports the service interfaces that the corresponding service was registered with and that are visible to the bundle.

Spring-DM supports sorted collections as well, both for set and list.

It is possible to specify a sorting order using either the comparator-ref attribute, or the nested comparator element. The comparator-ref attribute is used to refer to a named bean implementing java.util.Comparator. The comparator element can be used to define an inline bean. For example:

<set id="myServices" interface="com.xyz.MyService"
  comparator-ref="someComparator"/>

<list id="myOtherServices" 
  interface="com.xyz.OtherService">
  <comparator>
     <beans:bean class="MyOtherServiceComparator"/>
  </comparator>
</list>

To sort using a natural ordering instead of an explicit comparator, you can use the natural-ordering element inside of comparator. You need to specify the basis for the natural ordering: based on the service references, following the ServiceReference natural ordering defined in the OSGi Core Specification section 6.1.2.3; or based on the services themselves (in which case the services must be Comparable).

<list id="myServices" interface"com.xyz.MyService">
  <comparator><natural-ordering basis="services"/></comparator>
</list>

<set id="myOtherServices"interface="com.xyz.OtherService">
  <comparator><natural-ordering basis="service-references"/></comparator>
</set>

Note

For a sorted set, a SortedSet implementation will be created. However, since the JDK API does not provide a dedicated SortedListinterface, the sorted list will implement only the List interface.

6.2.2.1. Greedy Proxying


All OSGi services imported by a Spring-DM service collection publish and are type-compatible with the classes declared by the interfaces property. However, some services might expose additional (optional) classes that could be relevant to your application.

For these cases, Spring-DM collections offer a dedicated attribute called greedy-proxying which will cause the creates proxies to use all the classes advertised by the imported services, visible to the consuming importing bundle. Thus, it is possible to cast the imported proxies to classes different then those specified in the interfaces. For example, with the following list definition:

<list id="services" interface="com.xyz.SomeService" greedy-proxying="true"/>

one can do the following iteration (assuming MessageDispatcher type is imported by the bundle):

for (Iterator iterator = services.iterator(); iterator.hasNext();) {
	SomeService service = (SomeService) iterator.next();
	service.executeOperation();
	// if the service implements an additional type
	// do something extra
	if (service instanceof MessageDispatcher) {
		((MessageDispatcher)service).sendAckMessage();
	}
}

Note

Before using greedy proxies and instanceof statements, consider using a different interface/class for your services which provides better polymorphism and is more object-oriented.

6.2.2.2. Collection (list and set) element attributes


list and set elements support all the attributes available to reference element except the timeout attribute. See the following table as a summary of the list and set element attribute names, possible values and a short description for each of them.

Table 6.3. <list>/<set> attributes
Name Values Description
interface fully qualified class name (such as java.lang.Thread) The fully qualified name of the class under which the object will be exported.
filter OSGi filter expression (such as ((asynchronous-delivery=true)) OSGi filter expression that is used to constrain the set of matching services in the service registry.
bean-name any string value Convenient shortcut for specifying a filter expression that matches on the bean-name property that is automatically advertised for beans published using the <service> element.
context-class-loader client/service-provider/unmanaged Defines how the context class loader is managed when invoking operations on a service backing this service reference. The default value is client which means that the context class loader has visibility of the resources on this bundle's classpath. Alternate options are service-provider which means that the context class loader has visibility of resources on the bundle classpath of the bundle that exported the service, and unmanaged which does not do any management of the context class loader.
cardinality 0..N/1..N Defines the required cardinality of the relationship to the backing service. If not specified, the default-cardinality attribute will apply. A value is '1..N' means that a backing service must exist (this is a mandatory service reference). A value of '0..N' indicates that it is acceptable to be no backing service (an optional service reference).
comparator-ref any string valuem Named reference to a bean acting as comparator for the declaring collection. Declaring a comparator automatically makes the declaring collection sorted.
greedy-proxying true/false Indicates whether the proxies created for the imported OSGi services will be generated using just the classes specified (false) or all the classes exported by the service and visible to the importing bundle (true). The default value is false.

The table below lists the attributes available for the comparator/natural sub element.

Table 6.4. collection <comparator> attributes
Name Values Description
basis service/service-reference Indicate the element on which natural ordering should apply - service for considering the service instance and service-reference for considering the service reference instead of the service.

6.2.2.3. list / set and OSGi Service Dynamics


A collection of OSGi services will change its content during the lifetime of the application context since it needs to reflect the state of the OSGi space. As service are registered and unregistered, they will be added or removed from the collection.

While a reference declaration will try to find a replacement if the backing service is unregistered, the collection will simply remove the service from the collection. Like reference, a collection with cardinality 1..N is said to be mandatory while a collection with cardinality 0..N is referred to as being optional. If no matching service is available then only mandatory collections become unsatisfied. That is if no service is available invoking an operation on:

  • mandatory collection - will throw an unchecked ServiceUnavailableException.
  • optional collection - will not throw any exceptions (however the collection will be empty).

Just like reference, mandatory collections will trigger the unregistration of any exported service that depends upon it. See Section 6.5, “Relationship between the service exporter and service importer” for more information.

6.2.2.4. Iterator contract and service collections


The recommend way of traversing a collection is by using an Iterator. However, since OSGi services can come and go, the content of the managed service collection will be adjusted accordingly. Spring-DM will transparently update all Iterators held by the user so it is possible to safely traverse the collection while it is being modified. Moreover, the Iterators will reflect all the changes made to the collection, even if they occurred after the Iterators were created (that is during the iteration). Consider a case where a collection shrinks significantly (for example a big number of OSGi services are shutdown) right after an iteration started. To avoid dealing with the resulting 'dead' service references, Spring-DM iterators do not take collection snapshots (that can be inaccurate) but rather are updated on each service event so they reflect the latest collection state, no matter how fast or slow the iteration is.

It is important to note that a service update will only influence Iterator operations that are executed after the event occurred. Services already returned by the iterator will not be updated even if the backing service has been unregistered. As a side note, if an operation is invoked on such a service that has been unregistered, a ServiceUnavailableException will be thrown.

To conclude, while a reference declaration will search for candidates in case the backing service has been unregistered, a service collections will not replace unregistered services returned to the user. However, it will remove the unregistered services from the collection so future iterations will not encounter them.

Please note that the Iterator contract is guaranteed meaning that next() method always obey the result of the previous hasNext() invocation.

Table 6.5. Dynamic service collection Iterator contract
hasNext() returned value next() behaviour
true Always return a non-null value, even when the collection has shrunk as services when away.
false per Iterator contract, NoSuchElementException is thrown. This applies even if other services are added to the collection

The behaviour described above, offers a consistent view over the collection even if its structure changes during iteration. To simply refresh the iterator, call hasNext() again. This will force the Iterator to check again the collection status for its particular entry in the iteration.

In addition, any elements added to the collection during iteration over a sorted collection will only be visible if the iterator has not already passed their sort point.

6.2.3. Dealing with the dynamics of OSGi imported services


Whether you are using reference or set or list, Spring Dynamic Modules will manage the backing service. However there are cases where the application needs to be aware when the backing service is updated.

Such applications, that need to be aware of when the service backing a reference bean is bound and unbound, can register one or more listeners using the nested listener element. This element is available on both reference and set, list declarations. In many respects, the service importer listener declaration is similar to the service exporter listener declaration (Section 6.1.7, “Service registration and unregistration lifecycle”). The listener element refers to a bean (either by name, or by defining one inline) that will receive bind and unbind notifications. If this bean implements Spring-DM's org.springframework.osgi.service.importer.OsgiServiceLifecycleListener interface, then the bind and unbind operations in this interface will be invoked. Instead of implementing this interface (or in addition), custom bind and unbind callback methods may be named.

An example of declaring a listener that implements OsgiServiceLifecycleListener:

<reference id="someService" interface="com.xyz.MessageService">
  <listener ref="aListenerBean"/>
</reference>

An example of declaring an inline listener bean with custom bind and unbind methods:

<reference id="someService" interface="com.xyz.MessageService">
  <listener bind-method="onBind" unbind-method="onUnbind">
     <beans:bean class="MyCustomListener"/>
  </listener>
</reference>

If the listener bean implements the OsgiServiceLifecycleListener interface and the listener definition specifies custom bind and unbind operations then both the OsgiServiceLifecycleListener operation and the custom operation will be invoked, in that order.

The signature of a custom bind or unbind method must be one of:

public void anyMethodName(ServiceType service, Dictionary properties);

public void anyMethodName(ServiceType service, Map properties);

public void anyMethodName(ServiceReference ref);

where ServiceType can be any type. Please note that bind and unbind callbacks are invoked only if the backing service matches the type declared in the method signature( ServiceType). If you want the callbacks to be called no matter the type, use java.lang.Object as a ServiceType.

The properties parameter contains the set of properties that the service was registered with.

If the method signature has a single argument of type ServiceReference then the ServiceReference of the service will be passed to the callback in place of the service object itself.

When the listener is used with a reference declaration:

  • A bind callback is invoked when the reference is initially bound to a backing service, and whenever the backing service is replaced by a new backing service.
  • An unbind callback is only invoked when the current backing service is unregistered, and no replacement service is immediately available (i.e., the reference becomes unsatisfied).

When the listener is used with a collection declaration (set or list):

  • A bind callback is invoked when a new service is added to the collection.
  • An unbind callback is invoked when a service is unregistered and is removed from the collection.

Again note that service collections there is no notion of service rebind: services are added or removed from the collection.

Bind and unbind callbacks are made synchronously as part of processing an OSGi serviceChanged event for the backing OSGi service, and are invoked on the OSGi thread that delivers the corresponding OSGi ServiceEvent.

The table below lists the attributes available for the reference listener sub element.

Table 6.6. OSGi <listener> attributes
Name Values Description
ref bean name reference Name based reference to another bean acting as listener.
bind-method string representing a valid method name The name of the method to be invoked when a backing service is bound.
unbind-method string representing a valid method name The name of the method to be invoked when a backing service is bound.

6.2.4. Listener and service proxies


While the importer listener provides access to the OSGi service bound at a certain point, it is important to note that the given argument is not the actual service but a proxy. This can have subtle side effects especially with regards to service class name and identity. The reason behind using a proxy is to prevent the listener from holding strong reference to the service (which can disappear at any point). Listeners interested in tracking certain services should not rely on instance equality (==). Object equality (equals/hashcode) can be used but only if the backing service has exposed the aforementioned methods as part of its contract (normally by declaring them on a certain published interface/class). If these methods are not published, the proxy will invoke its own method, not the targets. This is on purpose since, while the proxy tries to be as transparent as possible, it is up to the developer to define the desired semantics.

Thus, it is recommended (especially for reference importers) to do tracking based on just the service interface/contract (not identity), service properties (see org.osgi.framework.Constants#SERVICE_ID) or service notification (bind/unbind).

6.2.5. Accessing the caller BundleContext


It is sometime useful for an imported service to know which bundle is using it at a certain time. To help with this scenarion, in Spring-DM imported services publish the importing bundle BundleContext through LocalBundleContext class. Each time a method on the importer is invoked, the caller BundleContext will be made available, using a ThreadLocal, through getInvokerBundleContext().

Please be careful when using this class since it ties your code to Spring-DM API.

  6.3. Exporter/Importer listener best practices


As mentioned above, Spring-DM exporter and importer allow listeners to be used for receiving notifications on when services are bound, unbound, registered or unregistered. Below you can find some guidance advices when working with listeners:

  • Do not execute long activity tasks inside the listener. If you really have to, use a separate thread for executing the work. The listener are called synchronously and so try to be as fast as possible. Doing work inside the listener prevents other the event to be sent to other listeners and the OSGi service to resume activity.
  • Use listener custom declaration as much as possible - it doesn't tie your code to Spring-DM API and it doesn't enforce certain signature names.
  • If find yourself repeating bind/unbind method declarations for your listener definitions, consider using Spring bean definition inheritance to define a common definition that can be reused and customized accordingly.
  • Prefer java.util.Map instead of java.util.Dictionary class. The first is an interface while the latter is a deprecated, abstract class. To preserve compatibility, Spring-DM will pass to the listeners a Map implementation that can be casted, if needed, to a Dictionary.
  • Be careful when using overloaded methods: all methods matching a certain service type will be called which is not always expected. Consider the following listener:

public class MyListener {
    void register((1)Object service, Map properties);
    void register((2)Collection dataService, Map properties);
    void register((3)SortedSet orderedDataService , Map properties);
}

(1) Object type - will match all services for which the listener is triggered. This method will be always called.
(2) Collection type - if this method is called, the Object method is also called. 
(3) SortedSet type - if this method is called, then both the Object and Collection methods are called.

6.3.1. Listener and cyclic dependencies


There are cases where an exporter/importer listener needs a reference back to the bean it is defined on:

<bean id="listener" class="cycle.Listener">                                              (1)
    <property name="target" ref="importer" />                                            (2)
</bean>

<osgi:reference id="importer" interface="SomeService">                                   (3)
    <osgi:listener bind-method="bind" ref="listener" />                                  (4)
</osgi:reference>

(1) Listener bean
(2) Dependency listener -> importer
(3) Importer declaration
(4) Dependency importer -> listener

The declaration above while valid, creates a dependecy between the listener and the importer it is defined upon. In order to create the importer, the listener has to be resolved and created but in order to do that, the importer called service needs to be retrieved (instantiated and configured). This cycle needs to be broken down so that at least one bean can be fully created and configured. This scenario is supported by Spring-DM for both exporter and importers however, if the listener is defined as a nested bean, the cycle cannot be resolved:

<osgi:reference id="importer" interface="SomeService">                                   (1)
    <osgi:listener bind-method="bind">                                                   (2)
        <bean class="cycle.Listener">                                                    (3)
            <property name="target" ref="importer" />                                    (4)
        </bean>
    </osgi:listener>
</osgi:reference>

(1) OSGi service importer
(2) Dependency between importer -> listener
(3) Nested listener declaration
(4) Dependency nested listener -> importer

The example above will fail since service bean cannot be initialized as it depends on the listener. The same cycle was seen before but in this case there is subtle yet big different from the container perspective - the listener is declared as a nested/inner-bean (hence the missing bean id). Inner beans have the same life cycle as their declaring parents and do not have any name. By definition, they are not tracked by the container and are simply created on demand. Since the importer cannot be partially created and the nested listener cannot be cached, the container cannot break the cycle and create the beans. While the two configurations shown above seem similar, one works while the other does not. Another reason to not use cycles unless you really, really have to.

To conclude, if you need inside the listener to hold a reference to the exporter/importer on which the listener is declared, either declare the listener as a top-level bean (as shown before) or consider doing dependency lookup. However, the latter approach requires extra contextual information such as the BeanFactory to use and the bean name and is more fragile then dependency injection.

Note
For those interested in the technical details, neither the exporter and importer cannot be partially initialized since they require the application context ClassLoader which is requested through the BeanClassLoaderAware which relies on a buit-in BeanPostProcessor which is applied only after the bean has been configured and is ready for initialization. If the ClassLoader was not required then the exporter/importer could have been partially initialized and the case above supported.


(訳注:ここは6.3.1.横下の囲み記事です)

Beans and Cycles

Cyclic dependencies (A depends on B which depends back on A) increase the complexity of your configuration and in most cases indicate a design issue. What beans should be created and destroyed first for example? While they are a bad practice, the Spring container makes a best attempt to solve the cyclic configurations when singletons are involved (since the instances can be cached). However this does not work all the time and depends heavily on your specific configuration (Can the bean class be partially initialized ? Does it rely on special Aware interfaces? Are BeanPostProcessors involved?)

(訳注:囲み記事ここまで)



  6.4. Service importer global defaults


The osgi namespace offers two global attributes for specifying default behaviours for all importers declared in that file.

Thus, when using the osgi namespace to enclose set, list or reference elements, one can use:

  • default-timeout - can be used to specify the default timeout (in milliseconds) for all importer elements that do not explicitly specify one. For example:

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:osgi="http://www.springframework.org/schema/osgi"                            (1)
          osgi:default-timeout="5000">                                                   (2)

  <reference id="someService" interface="com.xyz.AService"/>                             (3)

  <reference id="someOtherService" interface="com.xyz.BService"
       timeout="1000"/>                                                                  (4)

</beans:beans>

(1) Declare osgi namespace prefix.
(2) Declare default-timeout(in miliseconds) on the root element. If the default is not set, it will have a value of 5 minutes. In this example, the default value is 5 seconds.
(3) This reference will inherit the default timeout value since it does not specify one. This service reference will have a timeout of 5 seconds.
(4) This reference declares a timeout, overriding the default value. This service reference will have a timeout of 1 second.

  • default-cardinality - can be used to specify the default cardinality for all importer elements that do not explicitly specify one. Possible values are 0..X and 1..X where X is substituted at runtime to 1 for reference elements or N for collection types such as set or list.

Consider the following example:

<beans:beans
      xmlns="http://www.springframework.org/schema/osgi"                                 (1)
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:beans="http://www.springframework.org/schema/beans"                          (2)
      xmlns:osgi="http://www.springframework.org/schema/osgi"                            (3)
         osgi:default-cardinality="0..X"                                                 (4)
         default-lazy-init="false">                                                      (5)

  <reference id="someService" interface="com.xyz.AService"/>                             (6)

  <set id="someSetOfService" interface="com.xyz.BService"/>                              (7)

  <list id="anotherListOfServices" interface="com.xyz.CService" cardinality="1..N"/>     (8)

</beans:beans>

(1) Declare Spring Dynamic Modules schema as the default namespace.
(2) Import Spring Framework beans schema and associate a prefix with its namespace (beans in this example).
(3) Import Spring Dynamic Modules schema and associate a prefix with its namespace (osgi in this example). This is required since the global attributes have to be declared to an element (beans) belonging to another schema. To avoid ambiguity, the Spring-DM schema is imported under a specified prefix as well.
(4) Declare default-cardinality on the root element. If the default is not set, it will have a value of 1..N. In this example, the default value is 0..N. Note the osgi prefix added to the global attribute.
(5) beans element attributes (such as default-lazy-init) do not need a prefix since they are declared as being local and unqualified (see the beans schema for more information).
(6) The reference declaration will inherit the default cardinality value since it does not specify one. As reference represents a single service, its cardinality will be 0..1. 
(7) The set declaration will inherit the default cardinality value since it does not specify one. As set (or list) represents a collection of service, its cardinality will be 0..N. 
(8) The list declaration specifies its cardinality (1..N), overriding the default value.

The default-* attributes allow for concise and shorter declarations as well as easy propagation of changes (such as increasing or decreasing the timeout).

  6.5. Relationship between the service exporter and service importer


An exported service may depend, either directly or indirectly, on other services in order to perform its function. If one of these services is considered a mandatory dependency (has cardinality 1..x) and the dependency can no longer be satisfied (because the backing service has gone away and there is no suitable replacement available) then the exported service that depends on it will be automatically unregistered from the service registry - meaning that it is no longer available to clients. If the mandatory dependency becomes satisfied once more (by registration of a suitable service), then the exported service will be re-registered in the service registry.

This automatic unregistering and re-registering of exported services based on the availability of mandatory dependencies only takes into account declarative dependencies. If exported service S depends on bean A, which in turn depends on mandatory imported service M, and these dependencies are explicit in the Spring configuration file as per the example below, then when M becomes unsatisfied S will be unregistered. When M becomes satisfied again, S will be re-registered.

<osgi:service id="S" ref="A" interface="SomeInterface"/>

<bean id="A" class="SomeImplementation">
   <property name="helperService" ref="M"/>
</bean> 

<!-- the reference element is used to refer to a service
     in the service registry -->
<osgi:reference id="M" interface="HelperService"
     cardinality="1..1"/>

If however the dependency from A on M is not established through configuration as shown above, but instead at runtime through for example passing a reference to M to A without any involvement from the Spring container, then Spring Dynamic Modules will not track this dependency.



次へ?
前へ
目次へ
技術的雑談に戻る

最終更新日時:最終更新時間:2008年07月29日 17時39分37秒
トップページに戻る