GroovyでOSGiサービスを書いてGradleでサクッとバンドル化する方法

はじめに

最近、Twitterのタイムラインなどをはじめ、至る所で「OSGi」について言及されてるので、ここらで試しておこうと。


今回動作確認で使ったOSGi実装は、Apache Felix(http://felix.apache.org/site/index.html)です。
Equinoxでもどっちでもよかったのですが、まあ何となく。適当です。お好きな方をどうぞ。


参考にしたサイトはひたすらブクマしたので、よろしければそちらをどうぞ。


一応、Groovy&Gradle&OSGiということで、以下は必読です。

サンプルコード

サンプル一式はgithubにコミットしておきました。
たいした物ではないですが、設定とかベースになる物があった方が取っつきやすいと思うので、よかったらどうぞ。


ちなみに、こんな↓Activatorになってます。

class GroovyOSGiSampleActivator implements BundleActivator {
    void start(BundleContext context) {
        println "Groovy BundleActivator started..."
    }
    void stop(BundleContext context) {
        println "Groovy BundleActivator stopped. Bye!!"
    }
}

サンプルの試し方

必要な物
  • Groovy 1.7
  • Gradle 0.8+
  • Apache Felix 2.0.1
ビルドする
$ cd $SAMPLE_HOME
$ gradle clean jar

ビルドに成功すれば、$SAMPLE_HOME/build/libs配下にjarファイルが生成されます。
build.gradleで設定してあるOSGiプラグインのおかげで、OSGiバンドルに必要なエントリが書かれたMANIFEST.MFもきちんと含まれています。

動かしてみる

※でコメント書きます。

$ cd $FELIX_HOME
$ java -jar bin/felix.jar
    ※binの中にはいっちゃだめ。この位置関係が重要。

Welcome to Felix
================

-> 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)
    ※初期状態。デフォルトのバンドルはこれだけ。
-> install file://$FELIX_HOME/groovy-osgi-sample/build/libs/groovy-osgi-sample-0.1-SNAPSHOT.jar
    ※先ほど作ったjarをインストールします。$FELIX_HOMEのところは実際の絶対パスを指定してください。
Bundle ID: 18
    ※このときは、ID=18のバンドルとしてインストールされたということ。
-> 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)
[  18] [Installed  ] [    1] GroovyOSGiSample (0.1)
-> start 18
    ※起動してみると...
org.osgi.framework.BundleException: Unresolved constraint in bundle org.jggug.kobo.groovy-osgi-sample [18]: package; (&(package=groovy.lang)(version>=1.7.0))
    ※Groovy関係のクラスが解決できないのでエラーになっちゃいました。
-> install file://$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar
Bundle ID: 19
    ※というわけで、Groovyもバンドルとしてインストールします。$GROOVY_HOMEのところは実際の絶対パスを指定してください。
-> 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)
[  18] [Installed  ] [    1] GroovyOSGiSample (0.1)
[  19] [Installed  ] [    1] Groovy Runtime (1.7.0)
-> start 18
    ※もう一度起動してみると...
Groovy BundleActivator started...
    ※やりましたね!!!
-> 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)
[  18] [Active     ] [    1] GroovyOSGiSample (0.1)
[  19] [Resolved   ] [    1] Groovy Runtime (1.7.0)
    ※無事に起動してます。これをみるとGroovyのバンドルはstartする必要はないようです。
-> stop 18
    ※バンドルを停止してみます。
Groovy BundleActivator stopped. Bye!!
    ※いい感じ。
-> 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)
[  18] [Resolved   ] [    1] GroovyOSGiSample (0.1)
[  19] [Resolved   ] [    1] Groovy Runtime (1.7.0)
    ※確かに止まっています。
-> start 18
    ※再びバンドルを起動して、
Groovy BundleActivator started...
-> update 18
    ※udpateを使うと、インストールしたバンドルをjarファイルから読み直してくれます。
Groovy BundleActivator stopped. Bye!!
Groovy BundleActivator started...
    ※起動時であればこのように自動的にstop→startになります。
-> 

build.gradleでMANIFEST.MFの設定をいじったり、GroovyOSGiSampleActivator.groovyを変更した後に、Gradleでビルドをし直してから、起動中のFelix君にupdateコマンドを実行すると、その場でサクサクと変更結果が確認できます。


build.groovyでImport-Packageの一部を削ってみたり、バージョンをずらしてみたり、GroovyOSGiSampleActivatorでprintlnの文字列を変えてみると、理解が深まりますね。


とりあえず、今日はここまで。