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 が scopeprototype であることを宣言していない限り、この引数にはサービスインスタンスが含まれます。この場合、この引数は null です (スコープが prototype の場合、登録時に利用可能なサービスインスタンスはありません)。
  • 第二の方法引数は、java.util.Map 型や java.util.Dictionary 型のいずれかである必要があります。このマップには、このサービス登録に関連付けられたサービスプロパティーが含まれています。