に引き続き、今回は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がコールバックメソッドとして呼び出されていることが確認できます。
次回は、今回作成したサービスを利用するクライアントを作成します。