Apache Felix に自作のバンドル(OSGi Bundle)を登録する
ServiceMix Kernel に採用されているオープンソース OSGi フレームワークの Apache Felix に関して、自作のバンドル(OSGi Bundle)を作成・登録してみる。
手順は以下の通り。
- Bundle クラス作成
- JAR ファイル作成
- インストール
作業準備として、Felix のアーカイブファイルをダウンロードサイトからダウンロードし、適当なディレクトリに解凍しておきます。
今回は以下の環境を使用しました。
Bundle クラス作成
まず、org.osgi.framework.BundleActivator インターフェースを実装した Bundle クラスを作成します。
BundleActivator インターフェースの start メソッドでは Bundle が開始された時の処理を、stop メソッドでは Bundle が停止された時の処理をそれぞれ実装します。
なお、start や stop メソッドの引数として与えられる BundleContext を活用すると、他の Bundle によって登録されているサービスを取得して使用したり、フレームワークからのイベント通知を受け取ったりする事ができるようです。
今回は、標準出力にログを出力するだけの簡単な実装を行いました。
SampleActivator.java
package sample; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class SampleActivator implements BundleActivator { public void start(BundleContext context) { System.out.println("start : " + getClass()); } public void stop(BundleContext context) { System.out.println("stop : " + getClass()); } }
JAR ファイル作成
先ほど作成した Bundle クラスをコンパイルし、JAR ファイル化します。
JAR ファイル化する際、META-INF/MANIFEST.MF ファイルに以下のような設定が追加されるようにします。
- Bundle-Name: Bundle名
- Bundle-Description: Bundleの説明
- Bundle-Vendor: ベンダー名
- Bundle-Version: バージョン
- Bundle-Activator: BundleActivator 実装クラス名
- Import-Package: import するパッケージ("," で区切って複数記述可)
Import-Package への org.osgi.framework の設定は必須になります。(Bundle クラスで org.osgi.framework.BundleActivator インターフェースを実装するため)
今回は Gant を使ってコンパイルと JAR ファイルの作成を実施することにします。
以下の Gant 用ビルドファイルでは、Bundle クラスをコンパイルするために Felix インストールディレクトリ 内の bin/felix.jar をクラスパスをに含むようにし、Ant.jar の実行時に MANIFEST.MF への設定追加を行っています。
build.gant
(注)FELIX_HOME 環境変数に Felix のインストールディレクトリを設定している事が前提
includeTargets << gant.targets.Clean Ant.property(environment: "env") felixHome = Ant.antProject.properties."env.FELIX_HOME" destDir = "dest" classesDir = "$destDir/classes" jarFile = "sample.jar" cleanDirectory << destDir target("default": "") { compile() } target(init: "") { path(id: "project.classpath") { pathelement(path: destDir) //felix.jar をクラスパスに追加するための設定 fileset(dir: felixHome) { include(name: "bin/*.jar") } } } target(compile: "") { depends(init) Ant.mkdir(dir: classesDir) Ant.javac(srcdir: "src", destdir: classesDir) { classpath(refid: "project.classpath") } } target(build: "") { depends(compile) Ant.jar(destfile: "${destDir}/${jarFile}", basedir: classesDir) { //MANIFEST.MF への設定追加 manifest { attribute(name: "Bundle-Name", value: "Sample Service") attribute(name: "Bundle-Description", value: "") attribute(name: "Bundle-Vendor", value: "") attribute(name: "Bundle-Version", value: "1.0.0") attribute(name: "Bundle-Activator", value: "sample.SampleActivator") attribute(name: "Import-Package", value: "org.osgi.framework") } } }
Gant を実行して jar ファイルを生成。
>gant build
インストール
Felix のインストールディレクトリ内で java -jar bin/felix.jar を実行し、Felix Shell を立ち上げ、作成した JAR ファイルをインストールします。
start コマンドに作成した JAR ファイルの URL を指定すると、インストール後に自動的に開始されます。(インストールだけを行う場合は install コマンドを使用)
今回使用した Felix Shell のコマンドは以下の通り。
- start [ID] : 指定 Bundle の開始
- start [URL] : インストール後に開始
- stop [ID] : 指定 Bundle の停止
- install [URL] : Bundle のインストール
- uninstall [ID] : 指定 Bundle のアンインストール
- ps : Bundle の一覧参照
- shutdown : コンソールを終了
Felix Shell を使ったインストールとアンインストール
(注)Felix のインストール先ディレクトリで実行
>java -jar bin/felix.jar ・・・ -> start file:///d:/felix_sample/sample.jar start : class sample.SampleActivator -> ps START LEVEL 1 ID State Level Name [ 0] [Active ] [ 0] System Bundle (1.4.0) [ 1] [Active ] [ 1] Apache Felix Shell Service (1.0.2) [ 2] [Active ] [ 1] Apache Felix Shell TUI (1.0.2) [ 3] [Active ] [ 1] Apache Felix Bundle Repository (1.2.1) [ 4] [Active ] [ 1] Sample Service (1.0.0) -> uninstall 4 stop : class sample.SampleActivator
以下でも可。
>java -jar bin/felix.jar ・・・ -> install file:///d:/felix_sample/sample.jar Bundle ID: 4 -> start 4 start : class sample.SampleActivator -> stop 4 stop : class sample.SampleActivator -> uninstall 4
Felix Shell が起動すると、カレントディレクトリに felix-cache ディレクトリが作成され、インストールされた Bundle が配置されるようになります。
Felix 1.2.1 のキャッシュディレクトリ
Felix 1.2.1 では、felix-cache の代わりにユーザーのホームディレクトリ内に .felix/[profile name] ディレクトリが作成される。([profile name] は 1.2.1 の Felix Shell の起動時に入力する profile name の値)