OSGiフレームワーク Apache Felix その2

blog1.mammb.com

に引き続き、今回はOSGiのサービスを作成します。

作成するサービス

作成するサービスは辞書サービスで、ある言葉が辞書に存在するかをチェックします。サービスの作成には、サービスのインターフェースを作成します。ファイル構成は以下のようになります。

felix-framework-2.0.0
└─ work
     ├─ example1
     └─ example2
          ├─ MANIFEST.MF
          └─ tutorial
               └─ example2
                    ├─ Activator.java
                    └─ service
                         └─ DictionaryService.java

example1 は前回作成分となります。

サービスインターフェースの作成

作成するサービスは辞書サービスで、ある言葉が辞書に存在するかをチェックします。サービスの作成には、サービスのインターフェースを作成します。

package tutorial.example2.service;

public interface DictionaryService {
    public boolean checkWord(String word);
}

サービスの実装とBundleActivatorの実装

package tutorial.example2;

import java.util.Properties;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;

import tutorial.example2.service.DictionaryService;

public class Activator implements BundleActivator {

    public void start(BundleContext context) {
        Properties props = new Properties();
        props.put("Language", "English");
        context.registerService(
            DictionaryService.class.getName(), new DictionaryImpl(), props);
    }
    public void stop(BundleContext context) { }

    private static class DictionaryImpl implements DictionaryService {
        String[] m_dictionary = { "osgi", "tutorial" };

        public boolean checkWord(String word) {
            for (String str : m_dictionary) {
                if (str.equals(word.toLowerCase())) return true;
            }
            return false;
        }
    }
}

BundleActivator を実装し、バンドルの startコールバック時に DictionaryService のインスタンスをサービスとして登録しています。DictionaryService のインスタンスはインナークラスとして定義しています。サービスの登録時に、DictionaryService のプロパティを同時に指定しています。

マニフェストの作成

MANIFEST.MFを以下の通り作成します。

Bundle-Name: English dictionary
Bundle-Description: A bundle that registers an English dictionary service
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: tutorial.example2.Activator
Export-Package: tutorial.example2.service
Import-Package: org.osgi.framework

Export-Packageとして、Activator が利用するサービスのパッケージを指定しています。

バンドル作成

作成したクラスとマニフェストからバンドルを作成します。

> cd work\example2
> javac -classpath ..\..\bin\felix.jar tutorial\example2\service\*.java tutorial\example2\*.java
> jar cfm example2.jar MANIFEST.MF tutorial\example2

バンドルのinstall

前回までで、Felixの状態は以下の通り、Service listener example がActive な状態となっています。

-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (2.0.0)
[   1] [Active     ] [    1] Apache Felix Bundle Repository (1.4.1)
[   2] [Active     ] [    1] Apache Felix Shell Service (1.4.0)
[   3] [Active     ] [    1] Apache Felix Shell TUI (1.4.0)
[   4] [Active     ] [    1] Service listener example (1.0.0)


start コマンドで今回作成したバンドルを install してスタートさせます。

-> start file:work\example2\example2.jar
Ex1: Service of type tutorial.example2.service.DictionaryService registered.
-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (2.0.0)
[   1] [Active     ] [    1] Apache Felix Bundle Repository (1.4.1)
[   2] [Active     ] [    1] Apache Felix Shell Service (1.4.0)
[   3] [Active     ] [    1] Apache Felix Shell TUI (1.4.0)
[   4] [Active     ] [    1] Service listener example (1.0.0)
[   5] [Active     ] [    1] English dictionary (1.0.0)
->

前回作成の Service listener example に、今回作成したバンドルの登録イベントが通知されてメッセージが出力されていることが分かります。


バンドルを stop してみましょう。

-> stop 5
Ex1: Service of type tutorial.example2.service.DictionaryService unregistered.
->

サービスの登録が解除されたメッセージが表示されます。
前回作成の該当箇所は以下となります。

    public void serviceChanged(ServiceEvent event) {
        String[] objectClass = (String[])
            event.getServiceReference().getProperty("objectClass");

        if (event.getType() == ServiceEvent.REGISTERED) {
            System.out.println("Ex1: Service of type " + objectClass[0] + " registered.");
        } else if (event.getType() == ServiceEvent.UNREGISTERING) {
            System.out.println("Ex1: Service of type " + objectClass[0] + " unregistered.");
        } else if (event.getType() == ServiceEvent.MODIFIED) {
            System.out.println("Ex1: Service of type " + objectClass[0] + " modified.");
        }
    }

サービスの登録、解除に応じて、他のバンドルのserviceChangedがコールバックメソッドとして呼び出されていることが確認できます。


次回は、今回作成したサービスを利用するクライアントを作成します。