前回はWeb層のOSGi Bundleを追加し、Service層のOSGi Bundleを共有する、ということをしました。では、今度はこの状態にService層のOSGi Bundleをバージョンアップして追加してみましょう。
つまり、
Web Bundle[Ver1.0] ------------> Service Bundle[Ver1.0] | Web Bundle[Ver1.1] ------| Service Bundle[Ver1.1]
ということをするわけですね。この時、両方のWeb BundleはどっちのService Bundleを見るんでしょうね?
ちなみに、OSGi Web BundleのMANIFEST.MFのImport-Packageは以下のようになっていました。
Import-Package: my.service.bundle;version="[1.0,2.0)",
この[1.0,2.0)は、my.service.bundleパッケージのバージョン1.0以上2.0未満(1.0 <= my.service.bundle < 2.0)に依存するという定義だそうです。ですので、1.1のService層のOSGi Bundleとは連携できるはずです。
なお、1.0固定にするためには[1.0,1.0]と[]で囲うらしいです。
では、Web層同様にバージョン1.0のBundleをコピーしてバージョン1.1を作成。
$ cp -R my-service-bundle my-service-bundle1.1
<modelVersion>4.0.0</modelVersion> <groupId>my.service.bundle</groupId> <artifactId>my-service-bundle</artifactId> <version>1.1.0</version> <packaging>jar</packaging>
MANIFEST.MFを修正。
Manifest-Version: 1.0 Export-Package: my.service.bundle;version="1.1.0" Bundle-Version: 1.1.0 Bundle-Name: My Service Bundle Bundle-ManifestVersion: 2 Import-Package: org.springframework.stereotype;version="[3.0,3.1)" Bundle-SymbolicName: my.service.bundle
「Bundle-Version」を上げるだけでなく、「Export-Package」に書かれたパッケージのバージョンも上げおきましょう。
あとはわかりやすくするために、Serviceが返却する文字列を変更しておきます。
package my.service.bundle.internal; import java.util.concurrent.atomic.AtomicInteger; import my.service.bundle.HelloService; import org.springframework.stereotype.Service; @Service("helloService") public class HelloServiceImpl implements HelloService { private AtomicInteger counter = new AtomicInteger(); @Override public String getVersion() { return "1.1"; } @Override public int getCount() { return counter.incrementAndGet(); } }
getVersionが「1.1」を返すようにしました。
ここから先は、STSのVirgo管理ツールでやるとなんかわかりにくそうなので、VirgoのAdmin Consoleを利用することにしました。
まずは、各プロジェクトを「mvn package」でパッケージングします。。この時、Service、Webの順でやりましょう。また、WebのビルドはServiceのJARがないと失敗するので、(あんまりやりたくないのですが)Serviceの「mvn package」後に「mvn install」を実行して、ローカルリポジトリにインストールした後で実行するようにしてください。
ではコマンドラインでVirgoを起動します。
$ $VWS_HOME/bin/startup.sh -clean
Admin Consoleにアクセスしてみます。
当然ですが、まだ何もありません。
んじゃ、OSGi Bundleをデプロイしてみましょっか。って、やってみたら、いきなり失敗。何で?と調べてみたら、MANIFEST.MFがなんかこんなことになっていました…。
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven Built-By: xxxxx Build-Jdk: 1.6.0_24
ほぉ、こっちで作ったMANIFEST.MFが無視されておるね?Mavenの設定が必要そうな感じなので、ちょっと調べてpom.xmlに以下の設定を追加。こちらは、Service用の設定です。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestFile>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifestFile> </archive> </configuration> </plugin> </plugins> </build>
なお、Web用だと以下のように書きます。
<plugin> <artifactId>maven-war-plugin</artifactId> <version>2.1-beta-1</version> <configuration> <packagingExcludes>WEB-INF/lib/**</packagingExcludes> <archive> <manifestFile>${basedir}/src/main/webapp/META-INF/MANIFEST.MF</manifestFile> </archive> </configuration> </plugin>
これに気付くのに、かなりハマりました…。
で、無事全部デプロイ完了。以下のURLにアクセスして、問題なく動くことを確認しておきます。
http://localhost:8080/my-web-bundle/hello/index
http://localhost:8080/my-web-bundle11/hello/index
続いて、Service Bundleのバージョン1.1をデプロイ。つまりは、こうなりました。
では、再度画面にアクセスすると…
なんと、変わりません…。あれ〜、そうなの??
ここで、VirgoのAdmin Consoleで「my.service.bundle 1.0.0」を選んで「Refresh」を選択すると…
おお、バージョン1.1に上がりましたよ!!自動的にロードし直すって動きはしないみたいですね。あと、参照していたWeb Bundle自体も再作成されるみたい。Web側のカウンタが1に戻っています。
つまりは、こういう状態になりました。
Web Bundle[Ver1.0] ------| Service Bundle[Ver1.0] | Web Bundle[Ver1.1] ------------> Service Bundle[Ver1.1]
ちなみに、この状態で「my.service.bundle 1.1.0」をAdmin Console上で「Stop」を選択して画面にアクセスすると、応答が返ってこなくなりました。依存関係があるやつを、いきなり停止してはいけないみたいですね。
では、今度は「my.service.bundle 1.1.0」を「Uninstall」して、画面にアクセスすると…
おお、1.0を見るように戻りましたよ!
どうも、新しいバージョンのBundleをデプロイしただけでは稼働中のBundleの参照先が切り替わるわけではないみたいですね。明示的に「Refresh」なり「Uninstall」なりした時に、再作成される模様。そうなると、「Stop」の意味がちょっとわかりませんが。
それにしても、稼働中にバージョンアップ/ダウンができるので、ちょっと面白いですね。実際に開発で使うと、相当ハマるでしょうが…。