EclipseCon 2011でコアOSGiプラットフォームの次リリースがアナウンスされ、近い将来リリースされるはずのドキュメントが最終公開ドラフトとして入手できる。BJ Hargrave氏がOSGi 4.3の新フィーチャに関して、これまでのリリースとの主要な差異をまとめるプレゼンを行った。
ジェネリックス
最も待たれていたフィーチャの1つがコアOSGi APIへのジェネリックスの追加である。これによって、キャストすることなしに、型安全なオペレーションが特定の型のサービスを探すことができる。しかし、OSGiは、組込みVM(1.5より前)上で走らせる必要があるので、1.5コンパイラを使って、コアAPIをビルドすることはできない。その代わりに、ほとんど忘れられたオプション -target jsr14
によって、ジェネリックスを使ったJavaコードをコンパイルし、1.4互換のJRE上で走らせることができる。このオプションは、JSR 14でのジェネリックスの移行の一部として導入され、今なお今日のコンパイラに存在する。これによって、クライアント コード(-target jsr14
付きで1.4で、あるいは、1.5以上でコンパイルされた)が以下のようにしてサービスを参照できる。
// OSGi 4.2 のやり方 // ServiceReference ref = context.getServiceReference( // LogService.class.getName()); // LogService log = (LogService)context.getService(ref); // OSGi 4.3 のやり方 ServiceReference<LogService> ref = context.getServiceReference( LogService.class); LogService log = context.getService(ref);
しかし、コアが完全なJava 1.5ではないので、他のフィーチャ(enum
やアノテーション)は、使えない。
Capabilities
OSGi環境における依存性の従来の単位は、packageあるいは bundle依存性(Import-Package
か Require-Bundle
)によって)。これらの依存性は、コードには上手くいくが、非コードの依存性を表す場合には、うまくない。例えば、バンドルがある程度のメモリーかwebサーバーの存在を必要とするような場合、特定のパッケージやバンドルで表わせない。
OSGi 4.3は、一般的な capabilitiesの概念を導入し、Require-Capability
と Provide-Capability
によって使うことができる。バンドルが解決される前に、非オプションの capability要求を満足しなければならない。このための典型的なユースケースは、OSGi Declarative Services(OSGi 宣言型サービス)のプロビジョンためのもので、これは、パッケージ依存性として、表されないが、バンドルが正しく解決されるために、必要なものである。
更に、最小限必要なバージョンは、capability 要求として、見せることができる。
// 古い方法 // Bundle-RequiredExecutionEnvironment: JavaSE-1.6 // 新しい方法 Require-Capability: osgi.ee;filter:="(&(osgi.ee="JavaSE")(version>=1.6))"
この一般化の結果として、Bundle-RequiredExecutionEnvironment
は、OSGi 4.3で非推奨(しかし未だ使える)である。
Remote Services (リモート サービス)
OSGi Remote Servicesは、新しいものではない( OSGi 4.2の概要の13章にあった)が、OSGi 4.3のコア仕様に昇格した。その結果、全てのOSGi 4.3ランタイムは、remote serviceをサポートする。
adapt
PackageAdmin
のようなサービスは、バンドルについてのメタ情報を提供するのに使えるが、型特定のアクセッサでバンドルのインターフェースを汚染することはない。これは、一般的にバンドルがいかに繋げられたか、あるいは、その開始レベルが何であったを知るためのお決まりのコードになってしまう。
物事を単純にするために、OSGi 4.3は、adapt(Class)
メソッドを Bundle
に導入した。Eclipseの IAdaptable パターンによく似て、Bundle
が既知の型に変換できる。要するに、もしバンドルが自分を特定の型に変換するのかを知っていれば、インスタンスが返される。もしそうでなければ(あるいは変換が禁じられていれば) null
が返される。これによって、PackageAdmin
と StartLevelAdmin
が以下のように簡単になる。
BundleWiring wiring = bundle.adapt(BundleWiring.class); // wiring.getRequirements(null) BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class); // bsl.getStartLevel()
既存のサービスはそのままだが、普通のユーザーは、実装が容易な新しい adaptパターンを使うのがお薦めである。
Weaving
Weavingサポートも公式化され、これによって拡張機能を、他のバンドルのメカニズムをローディングするクラスにプラグインできる。この技法はいくつかのランタイム システムで使われている。特にJPAを実装しているシステムや背後にデータベースを持つ永続化ストアで、特にその特別なクラス型のために使用されるコードを生成するために、この技法は使われている。Weavingフックのおかげで、以前はプロバイダ特有のメカニズムを使っていたOSGi フレームワークは、標準のメカニズを使うことができる。
入れ子のフレームワークは、非サポートに
しばらく、Equinoxで試験実装されていたが、入れ子のフレームワークのサポート(フレームワークが入れ子になったバージョンを起動できた)は、4.3の仕様からは外された。
その代わりに、もっと強力な BundleHook
と ResolverHook
API が加わり、拡張機能は、他からバンドルを隠すために、仮想のバンドルセットを作成できる。これは、サービスが他から見えないようにできるように、以前から使える ServiceHook
に続くものである。
こうしてお互いに見ることができないバンドル グループを作成して入れ子のフレームワークをエミュレートできる。この方法は、この新しいモデルをサポートするために作り直された新しい Virgo region model を実装するのに使われている。
二次的効果として、同じフレームワークに同じバンドル/バージョン ペアの複数バージョンをインストールできるようになる。ただし、これらはお互いに見えない必要がある。以前は、同じバンドルを2度目にインストールしようとするとエラーになった。このことはデフォルトでは実現できないが、フレームワークを起動するときに、プロパティ中の特性 org.osgi.framework.bsnversion=multiple
にして、複数インストールができるようにバンドルを設定すればいい。デフォルトでは、org.osgi.framework.bsnversion=single
に設定されている。
要約
新しいOSGiの仕様は、フレームワークに幾つもの有用なフィーチャをもたらすことになる。古いフレームワークをサポートする必要のないバンドルであれば、新ジェネリックAPIを使えるだけで、乗り換える充分な理由になるだろう。入れ子のフレームワークと weavingは、直接的な効果は、なさそうであるが、これらを使って低レベルなライブラリを実装すれば、標準化されたフックを使うことになり、色々なOSGiフレームワーク間におけるプラットフォームの相互運用性が増すだろう。
仕様は、まだ公式にリリースされていないが、今年のEclipseリリースの前には入手できると思われる。 Equinox 3.7による参照実装が宣言されそうだからである。