と言うわけで、とっかかりになるような簡単な OSGi バンドルを作ってみる。ただし一個のバンドルで"Hello World"をやっても何が OSGi なのか分からないので、サービス用とクライアント用の二つのバンドルを、OSGiを介在させて連携させてみる。
モノは、Apache の OSGi release4 実装、Felix を使用。
■ こんな作り
- Greeting Service
- 名前を受け取り、その名前を含むあいさつを返すメソッドを持つサービス
- Greeting Service Client
- 標準入力から読み取った名前を Greeting Service に渡し、結果を標準出力に表示する。ただし、Greeting Service が動いてなかったら、サービスが無い旨を表示する。
- 環境
- felix-framework-2.0.1 jdk1.6.0_13
■ 作り方
今回は IDE 等を使わずに、cygwin で vi、javac、jar を使って実装してみる。 c:\work\の下で作業すると仮定する。
◆ Greeting Service
適当な作業ディレクトリ(仮に c:\work\service とする)を作る。 以下のようにソース群を書き、パッケージ名と適当に対応させたディレクトリに置く。
- GreetingService.java: サービスの I/F を定義
package trial1.service; public interface GreetingService { public String greet(String name); }
- GreetingServiceImpl.java: サービスの I/F を実装
package trial1.service.impl; import trial1.service.GreetingService; public class GreetingServiceImpl implements GreetingService { public String greet(String name) { return "Hello " + name + "!"; } }
- Activator.java:OSGi コマンドの処理の実装
package trial1.service.activator; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import trial1.service.GreetingService; import trial1.service.impl.GreetingServiceImpl; public class Activator implements BundleActivator { public void start(BundleContext context) { context.registerService( GreetingService.class.getName(), new GreetingServiceImpl(), null); } public void stop(BundleContext context) {} }
- この時点で javac でコンパイルできるので、classes 下にでも classファイルを作っておく。(クラスパスに felix.jar が含まれている事が必要。)
$ javac -d classes trial1/service/activator/Activator.java
- 以下のような manifest.mfを書く: 上3行は適当だけど、下3行は大事。
Bundle-Name: Greeting Service Bundle-Description: A bundle that registers an Greeting service Bundle-Version: 1.0.0 Bundle-Activator: trial1.service.activator.Activator Export-Package: trial1.service Import-Package: org.osgi.framework
- ここで service.jar に丸めて、とりあえずサービス側は終わり
$ jar cfm service.jar manifest.mf -C classes trial1/service/
jar の中身はこんな風になる$ jar tvf service.jar 0 Mon Nov 02 02:03:10 JST 2009 META-INF/ 312 Mon Nov 02 02:03:10 JST 2009 META-INF/MANIFEST.MF 0 Mon Nov 02 01:58:44 JST 2009 trial1/service/ 0 Mon Nov 02 01:58:44 JST 2009 trial1/service/activator/ 736 Mon Nov 02 01:58:44 JST 2009 trial1/service/activator/Activator.class 183 Mon Nov 02 01:58:44 JST 2009 trial1/service/GreetingService.class 0 Mon Nov 02 01:58:44 JST 2009 trial1/service/impl/ 546 Mon Nov 02 01:58:44 JST 2009 trial1/service/impl/GreetingServiceImpl.class
- 別の作業ディレクトリ(仮に c:\work\client とする)を適当に作る。
- Activator.java を書いて、適当にパッケージに合わせたフォルダに置く。
package trial1.client.activator; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Filter; import org.osgi.util.tracker.ServiceTracker; import trial1.service.GreetingService; public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { Filter filter = context.createFilter( "(&(objectClass=" + GreetingService.class.getName() + "))"); ServiceTracker tracker = new ServiceTracker(context, filter, null); tracker.open(); try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Enter name: "); String name = in.readLine(); GreetingService service = (GreetingService) tracker.getService(); if (null == service) System.out.println("no available service"); else System.out.println(service.greet(name)); } catch (Exception ex) { } } public void stop(BundleContext context) {} }
- ここでコンパイル。但し、クラスパスには felix.jar と上で作った service.jar を含めておく。
javac -d classes trial1/client/activator/Activator.java
- manifest.mf は以下のように書く。大事なのは下4行。
Bundle-Name: Greeting Service Client Bundle-Description: A greeting service client Bundle-Version: 1.0.0 Bundle-Activator: trial1.client.activator.Activator Import-Package: org.osgi.framework, org.osgi.util.tracker, trial1.service
- client.jar に丸める。
$ jar cfm client.jar manifest.mf -C classes trial1/client/
以下のような中身になっている事を確認$ jar tvf client.jar 0 Mon Nov 02 02:12:44 JST 2009 META-INF/ 308 Mon Nov 02 02:12:44 JST 2009 META-INF/MANIFEST.MF 0 Mon Nov 02 02:10:56 JST 2009 trial1/client/ 0 Mon Nov 02 02:10:56 JST 2009 trial1/client/activator/ 1652 Mon Nov 02 02:10:56 JST 2009 trial1/client/activator/Activator.class
■ 確認
◆デプロイ
-> install file:/c:/work/service/service.jar Bundle ID: 23 -> install file:/c:/work/client/client.jar Bundle ID: 24ここで ps と打ち込んでみると以下のような感じ
-> ps START LEVEL 1 ID State Level Name [ 0] [Active ] [ 0] System Bundle (2.0.1) [ 1] [Active ] [ 1] Apache Felix Bundle Repository (1.4.2) [ 2] [Active ] [ 1] Apache Felix Shell Service (1.4.1) [ 3] [Active ] [ 1] Apache Felix Shell TUI (1.4.1) [ 23] [Installed ] [ 1] Greeting Service (1.0.0) [ 24] [Installed ] [ 1] Greeting Service Client (1.0.0)Greeting Service(23) が Active になっていないのを知りつつ、あえてGreeting Service Client(24) を開始してみる。
-> start 24 Enter name: World no available serviceちゃんと必要なサービスが無い旨が表示されていて、期待通り。 次にGreeting Service(23) を起動してから、Client(24)を開始してみる。
-> stop 24 -> start 23 -> start 24 Enter name: World Hello World!できた。ちゃんとサービスとクライアントが連携して"Hello World!"が表示された。
■ 資料
・参考にしたチュートリアル→Apache Felix OSGi Tutorial
・OSGi のJavaDoc →OSGi"! Service Platform Release 4 Version 4.2.0
0 件のコメント:
コメントを投稿