OSGi AllianceはOSGi概要バージョン5を発表した。The Core OSGi Release 5は2012年6月から利用可能になっており、企業向けの仕様は今年の始めにリリースされている。
OSGi概要(OSGi Compendium)はサービスの集合であり、バージョン情報とAPI定義を持っている。概要自体はコアOSGiのリリースの一部である必要はないが、アプリケーションのモジュール化に利用されることもある。Equniox、Felix、その他のOSGiプロジェクトはある程度、OSGi概要の仕様を実装している。
概要の中に、Service Tracker APIとSCA Configuration APIがないことに驚く読者もいるだろう。しかし、Service Tracker APIはコアへ、SCA Configuration APIはエンタープライズへそれぞれ移行している。APIは多くのRFCに準拠しており(RFC701はTracker、RFC129はSCA Configuration)。レビュープロセスが始まり、いくつかの仕様はGitHubで確認できる。
では、今回の概要では何が新しくなったのか。バンドルへ構成情報を渡していたConfigAdminのバージョンが1.4から1.5になった。また、Repository Service、Service Loader Mediator、Subsystem、Common NamespacesとResolver Serviceなどに新しいAPIが追加された。
Config Admin
Config Admin 1.5はtargeted PIDsに対する新しい仕様が含まれている。Config Adminは形式化されたPID(Persistent IDentity)名を使い、水平バーを使って、異なるバージョンのバンドルを指定できる。
- com.example.config|com.example.bundle|1.2.3|http://example.com/config.jar
- com.example.config|com.example.bundle|1.2.3
- com.example.config|com.example.bundle
永続化された識別子には特定のバンドル向けの情報が含まれる。Bundle-SymbolicNameとBundle-Versionを使って、構成を絞り込みオプションを特定することもできる。実行時は、最も絞り込まれた構成が適用される。Javaのリソースバンドルの国際化ルーチンが利用可能な特定の言語の値を利用するのと同じ仕組みだ。また、この新しい仕組みに利用できるマネージドサービスファクトリーにも変更が加えられている。
Repository ServiceとResolver Service
Repository ServiceはResolver Serviceと共に動作し、特定のリポジトリ(例えばMaven、P2、OBR、NuGet)のストレージとネットワークプロトコルを抽象化し、これらのリポジトリに対する制約を解決する方法を提供する。制約はOSGi Requirement Capabilityを使う。OSGi Requirement Capabilityは特定のOSGiモジュールを使うときに必要となるもの(パッケージのインポートや最小の実行環境、プラットフォームやプロセッサのようなフィルタ)を表している。
Maven Centralのようなリポジトリとは違い、OSGiリポジトリは保持しているコンポーネントの詳細な情報を必要とし、コンテンツ一式の解釈可能なXML注釈を返却する機能を必要とする。この仕組みはローカルのファイルベースのリポジトリでは上手く動作するが、大規模なリポジトリにスケールアウトできない可能性がある。OSGiリポジトリの仕様はobr
というかたちで以前に決まっていた。この仕様とRepository Serviceの違いは、Repository ServiceはP2のような他のリポジトリも含むことができるという点だ。
依存関係を解決するために、Resolver Serviceは一般的な要件とアセットに関する知識を取得して、どのアセットがどの要件と整合するかについてのプランを提供する。これは、Mavenの世界のAetherの機能に似ている。OSGiの場合、このような機能を提供するのEquinoxやFelixのようなランタイムエンジンで、ローカルのJARに基づいてバンドルを解決する。Resolver Serviceはこの仕組みを外部サービスとして提供し、ツールやユーティリティが以前は内部用だったAPIを利用する。
Service Loader Mediator
Java Service Loaderは汎用のサービスローダの仕組みとして欠陥があった実装だった。単一のClassLoader上で動作し、静的なバインディングしか提供しなかった。OSGiが複数のClassLoaderを使い動的な解決に対応するので、Service Loaderも修正が必要だ。
Service Loader Mediatorはまさにその修正を提供する。バイトコードウェービングで、Java Service Loaderの呼び出しを複数クラスのロードができる適切なラッパーに置き換える。また、サービスローダを有効にする必要があるバンドルを検出することで、必要なコードの実行量を減らし、既存のJARがJavaパッケージを利用できるようにする。そして、OSGi属性をマニュフェストに含めることで、OSGi属性がService Loader Mediatorの処理に加わることになり、バンドルは簡単にアップグレードできるようになる。
さらに、このService Loader MediatorはサービスをOSGiサービスとして公開するのにも使える。公開されたサービスは実行環境内のどこからでも利用できる。
Subsystem Service
OSGiのサブシステムは単一のOSGiランタイムが複数のアプリケーションのパーティションをホストできるようにする。これによって、アプリケーションはバンドルの依存を正確に定義できる(例えば、log4j 1.2.14)一方、同じOSGiフレームワーク上(別のサブシステム上)の他のアプリケーションは他のバージョンを参照することもできる(例えば、log4j 1.2.16)。
サブシステムはOSGiでの長期間の調査の結果生まれた、複数のアプリケーションを分離したかたちで実行する仕組みだ。以前はComposite BundlesやNested Frameworksという名で知られていたSubsystem Serviceの目的は複数のバンドルを同一の場所で動かす方法を汎用化することだ。OSGi Release 5でこの仕組みが初めて定義された。その他のイテレーションはRFCのレベルで行われている。
Eclipse Equinoxは古いバージョンであるNested Frameworksを実装している。しかし、Nested FrameworksはLunaでは削除される予定だ。一方、Eclipse Virgoはこのようなコンポジットシステムにとって重要であり、'ユーザ領域'と'カーネル領域'として提供される。
Common Namespace
OSGi 5の要求機能モデルは名前空間が設定された要求上に構築されている。これらの名前空間が設定された要求にはbundle-version
やbundle-symbolic-name
というような文字列が含まれており、追加の制約を提供するのに使われる。これについてはほとんどのユーザが知っている必要はない。リポジトリや依存関係を解決するサービスによって使われるだけだからだ。
結論
OSGi概要はコアやエンタープライズやレジデンシャルには適合しない部分を埋める。1年や2年間隔でサービス群として公開され、そのときの最終的な仕様の一部を表している。レビュー期間が始まれば、これらの仕様もインタラクティブに提供されるようになるだろう。皮肉にも、モジュラリティに基づいている組織にとって、多くの仕様文書はさまざまAPIの巨大な集積であり、それぞれのAPIの進化の速度も異なる。多くは(例えばHttpService)は過去のリリースの中でも変わらないが、概要のドキュメントの中には毎年記載がある。
クラウド事業者、特にEclipse Virgoのプラットフォームやその他の高モジュール化された環境に属している事業者はサブシステムの仕様を魅力的に感じるはずだ。リポジトリの仕様は現在OBRを使っている人にとっては興味深いかもしれない。しかし、少なくともこれからの数年のリリースでP2が一般的なリポジトリサービスになることはないだろう。一方、すべての人に利益があるのは、Service Loader Mediatorだろう。