12.2. サービスのエクスポート
概要
このセクションでは、Java オブジェクトを OSGi サービスレジストリーにエクスポートして、OSGi コンテナー内の他のバンドルからサービスとしてアクセスできるようにする方法について説明します。
単一のインターフェイスでのエクスポート
単一のインターフェイス名で OSGi サービスレジストリーにサービスをエクスポートするには、ref 属性を使用して関連するサービス Bean を参照する service 要素を定義し、interface 属性を使用してパブリッシュされたインターフェイスを指定します。
たとえば、例12.1「単一のインターフェイスを使用したサンプルサービスのエクスポート」 に記載されている Blueprint 設定コードを使用して、org.fusesource.example.Account インターフェイス名の下にある SavingsAccountImpl クラスのインスタンスをエクスポートできます。
例12.1 単一のインターフェイスを使用したサンプルサービスのエクスポート
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
<service ref="savings" interface="org.fusesource.example.Account"/>
</blueprint>
ref 属性は、対応する Bean インスタンスの ID を指定し、interface 属性は OSGi サービスレジストリーに登録されているパブリック Java インターフェイスの名前を指定します。この例で使用されているクラスとインターフェイスは、例12.2「サンプルアカウントクラスとインターフェイス」 に示します。
例12.2 サンプルアカウントクラスとインターフェイス
package org.fusesource.example
public interface Account { ... }
public interface SavingsAccount { ... }
public interface CheckingAccount { ... }
public class SavingsAccountImpl implements SavingsAccount
{
...
}
public class CheckingAccountImpl implements CheckingAccount
{
...
}複数のインターフェイスを使用したエクスポート
複数のインターフェイス名の下にある OSGi サービスレジストリーにサービスをエクスポートするには、ref 属性を使用して関連するサービス Bean を参照する service 要素を定義し、interfaces 子要素を使用してパブリッシュされたインターフェイスを指定します。
たとえば、次の Blueprint 設定コードを使用して、パブリック Java インターフェイス org.fusesource.example.Account および org.fusesource.example.SavingsAccount のリストの下にある SavingsAccountImpl クラスのインスタンスをエクスポートできます。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
<service ref="savings">
<interfaces>
<value>org.fusesource.example.Account</value>
<value>org.fusesource.example.SavingsAccount</value>
</interfaces>
</service>
...
</blueprint>
interface 属性と interfaces 要素は、同じ service 要素で同時に使用できません。どちらか一方を使用する必要があります。
自動エクスポートによるエクスポート
実装されたすべてのパブリック Java インターフェイス下で、サービスを OSGi サービスレジストリーにエクスポートする場合には、auto-export 属性を使用してこれを簡単に実現する方法があります。
たとえば、実装されたすべてのパブリックインターフェイスで SavingsAccountImpl クラスのインスタンスをエクスポートするには、以下の Blueprint 設定コードを使用します。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/> <service ref="savings" auto-export="interfaces"/> ... </blueprint>
auto-export 属性の値 interfaces は、Blueprint が SavingsAccountImpl によって実装されたすべてのパブリックインターフェイスを登録する必要があることを示しています。auto-export 属性には、次の有効な値を指定できます。
disabled- 自動エクスポートを無効にします。これはデフォルトになります。
interfaces- 実装されているすべてのパブリック Java インターフェイスにサービスを登録します。
class-hierarchy-
Objectクラスを除き、独自のタイプ (クラス) およびすべてのスーパータイプ (スーパークラス) の下のサービスを登録します。 all-classes-
class-hierarchyオプションと同様ですが、実装されたすべてのパブリック Java インターフェイスも含まれます。
サービスプロパティーの設定
OSGi サービスレジストリーを使用すると、サービス プロパティー を登録済みサービスに関連付けることもできます。その後、サービスのクライアントは、サービスプロパティーを使用して、サービスを検索またはフィルターリングできます。サービスプロパティーをエクスポートしたサービスに関連付けるには、1 つ以上の beans:entry 要素が含まれる service-properties 子要素を追加します (サービスプロパティーごとに beans:entry 要素 1 つ)。
たとえば、bank.name 文字列プロパティーを普通預金口座サービスに関連付けるには、以下の Blueprint 設定を使用できます。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:beans="http://www.springframework.org/schema/beans"
...>
...
<service ref="savings" auto-export="interfaces">
<service-properties>
<beans:entry key="bank.name" value="HighStreetBank"/>
</service-properties>
</service>
...
</blueprint>
bank.name 文字列プロパティーの値が HighStreetBank の場合。文字列以外のタイプのサービスプロパティーを定義することができ、プリミティブタイプ、配列、およびコレクションもサポートされます。これらのタイプを定義する方法は、Spring Reference Guide の アドバタイズされたプロパティーのセットの制御 を参照してください。
entry 要素は Blueprint namespace に属している必要があります。Spring の Blueprint 実装での beans:entry 要素の使用は標準ではありません。
デフォルトのサービスプロパティー
以下のように、service 要素を使用してサービスをエクスポートするときに自動的に設定される可能性がある 2 つのサービスプロパティーがあります。
-
osgi.service.blueprint.compnameは、Bean がインライン (Bean がservice要素の子要素として定義される) の場合を除き、サービスのbean要素のidを常に設定します。インライン化された Bean は常に匿名です。 -
service.rankingは、ranking 属性がゼロ以外である場合に自動的に設定されます。
ランキング属性の指定
バンドルがサービスレジストリーでサービスを検索し、一致するサービスが複数見つかった場合は、ランキングを使用して、どのサービスが返されるかを判断できます。このルールは、ルックアップが複数のサービスに一致する場合は常に、最高ランクのサービスが返されるというものです。サービスランクは負ではない整数で、0 がデフォルトです。service 要素に ranking 属性を設定して、サービスランクを指定できます。以下に例を示します。
<service ref="savings" interface="org.fusesource.example.Account" ranking="10"/>登録リスナーの指定
サービスの登録および登録解除イベントを追跡する場合は、登録および登録解除イベント通知を受信する 登録リスナー コールバック Bean を定義できます。登録リスナーを定義するには、registration-listener 子要素を service 要素に追加します。
たとえば、以下の Blueprint 設定は、registration-listener 要素によって参照されるリスナー Bean listenerBean を定義し、Account サービスが登録または登録解除されるたびにリスナー Bean がコールバックを受信するようにします。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" ...>
...
<bean id="listenerBean" class="org.fusesource.example.Listener"/>
<service ref="savings" auto-export="interfaces">
<registration-listener
ref="listenerBean"
registration-method="register"
unregistration-method="unregister"/>
</service>
...
</blueprint>
registration-listener 要素の ref 属性がリスナー Bean の id を参照する場合は、registration-method 属性は登録コールバックを受信するリスナーメソッドの名前を指定し、unregistration-method 属性は登録解除コールバックを受信するリスナーメソッドの名前を指定します。
以下の Java コードは、登録および登録解除のイベントの通知を受信する Listener クラスの定義例を示しています。
package org.fusesource.example;
public class Listener
{
public void register(Account service, java.util.Map serviceProperties) {
...
}
public void unregister(Account service, java.util.Map serviceProperties) {
...
}
}
メソッド名 register および unregister は、それぞれ registration-method 属性および unregistration-method 属性によって指定されます。これらのメソッドの署名は、次の構文に準拠している必要があります。
-
最初のメソッド引数: サービスオブジェクトのタイプから割り当て可能な任意のタイプ T。つまり、サービスクラスのスーパータイプクラス、またはサービスクラスによって実装されるインターフェイス。サービス Bean が
scopeがprototypeであることを宣言していない限り、この引数にはサービスインスタンスが含まれます。この場合、この引数はnullです (スコープがprototypeの場合、登録時に利用可能なサービスインスタンスはありません)。 -
第二の方法引数は、
java.util.Map型やjava.util.Dictionary型のいずれかである必要があります。このマップには、このサービス登録に関連付けられたサービスプロパティーが含まれています。