JSR 291: Dynamic Component Support for Java SE

本連載では第12回の記事で、Javaプラットフォームにおけるモジュラリティをサポートする「JSR 277: Java Module System」について取り上げた。JCPにはJSR 277と同様にモジュラリティの強化を目指すAPIとして、「JSR 291: Dynamic Component Support for Java SE」がある。

JSR 291は、標準化団体OSGi Allianceによって提供されているダイナミックコンポーネントモデル仕様をベースとしたダイナミックコンポーネントフレームワークを、Java SE環境で利用できるようにしようというもの。OSGi仕様ではJavaプラットフォームにおけるアプリケーションのコンポーネント化やライフサイクル管理やサービスリポジトリなどをサポートする。標準のJava SEにはコンポーネントを動的にインストール/起動/停止/アンインストールするような機能は用意されていないが、JSR 291を利用すればそれが可能になる。

JSR 277とJSR 291はいずれもJavaプラットフォームのモジュラリティに関する機能を提供するものだが、前者の目的がJava SEに対して静的なモジュールシステムを追加することなのに対して、後者の目的はJavaプラットフォーム上で動的に着脱可能なコンポーネントシステムを提供することにある。したがってJSR 291は既存のJavaプラットフォームを対象としてデザインされているという点が、JSR 277の思想とは大きく異なっている。

それに加えて、JSR 291はOSGi R4というすでに十分に洗練された仕様をベースとしている。とくにレガシーアプリケーション開発に関してはOSGiの長所が生きてくる。また、Java MEを対象とした同様のフレームワークであるJSR 232との互換性が考慮されている点にも注目したい。

なお、JSR 277とJSR 291の違いについては、スペックリードであるGlyn Normington氏のブログにおいてより詳細に解説されている。

OSGiフレームワークを試す

JSR 291の参照実装は公開されていないが、OSGi仕様のフリーな実装としてはEclipseプロジェクトによって「Equinox」が公開されている。これはEclipseのプラグインの仕組みを提供するツールとして開発され、v3.0以降で利用されている。EquinoxはJSR 291の実装候補にもなっており、その実力を試すには十分な機能を提供してくれる。

Equinoxの最新版であるバージョン3.3はこのページより入手できる。フレームワーク単体は「Equinox OSGi R4 framework(以下、Equinox framework)」というもので、「org.eclipse.osgi_<バージョン番号>.jar」というファイルをダウンロードすればよい。その他、Eclipse本体にもEquinoxが付属している。

まず、簡単なOSGiバンドルを作成する。バンドルを作成するには、バンドルの起動や停止を行うorg.osgi.framework.BundleActivatorインタフェースをimplementsする。今回はリスト1のようにHelloActivatorクラスを作成した。起動時および停止時に実行される処理は、それぞれstat/stopメソッドに実装する。

リスト1 HelloActivator.java - 簡単なOSGiバンドルの例

package apisample;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class HelloActivator implements BundleActivator {
    public void start(BundleContext context) throws Exception {
        System.out.println("Start hello1!");
    }

    public void stop(BundleContext context) throws Exception {
        System.out.println("Stop hello1!");
    }
}

jarコマンドを用いて作成したバンドルはJAR形式にまとめる。本稿の例では「hello1.jar」というファイル名にした(プロンプト1)。マニフェストファイルはリスト2のようにした。"Bundle-*"というのはバンドルのための情報である。

プロンプト1 JARファイルの作成

% jar cfm hello1.jar Manifest.mf apisample lib

リスト2 Manifest.mf - マニフェストファイル

Manifest-Version: 1.0
Class-Path: lib/org.eclipse.osgi_3.3.0.v20070530.jar
Bundle-ManifestVersion: 2
Bundle-Name: Hello Plug-in
Bundle-SymbolicName: hello1
Bundle-Version: 1.0.0
Bundle-Activator: apisample.HelloActivator
Bundle-Localization: plugin
Import-Package: org.osgi.framework;version="1.3.0"

Equinox frameworkはjavaコマンドを用いてプロンプト2のように起動する。するとOSGiコンソールが立ち上がる。

プロンプト2 Equinox frameworkの起動

% java -jar org.eclipse.osgi_3.3.0.v20070530.jar -console

osgi> 

OSGiコンソールでは次のようなコマンドでバンドルの管理などを行うことができる。たとえば「ss」と入力すれば、現在インストールされているすべてのバンドルの状態がプロンプト3のように表示される。その他の利用可能なコマンドについては、「?」と入力すればヘルプが表示される。

  • install <バンドルのURL> … 指定したURLからバンドルをインストールする
  • start <バンドル番号またはバンドル名> … 指定したバンドルを開始する
  • stop <バンドル番号またはバンドル名> … 指定したバンドルを停止する
  • ss … インストール済みのすべてのバンドルの状態を表示する

プロンプト3 すべてのインストール済みバンドルの状態を表示

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530

osgi> 

先ほど作成したバンドルをインストールするには、installコマンドを用いてプロンプト2.6のようにする。JARファイルの場所はURL形式で指定しなければならない。ssコマンドを使うと、新たに「hello1_1.0.0」というバンドルが追加されてステータス"INSTALLED"になっているのがわかる。

プロンプト4 バンドルのインストール

osgi> install file://[PATH_TO_BUNDOLE]/hello1.jar
Bundle id is 2

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530
2       INSTALLED   hello1_1.0.0

osgi> 

バンドルを開始するにはプロンプト5のようにする。開始時にはBundleActivatorのstart()メソッドが呼ばれ、ステータスは"ACTIVE"になる。

プロンプト5 バンドルの開始

osgi> start 2
Start hello1!

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530
2       ACTIVE      hello1_1.0.0

osgi> 

バンドルの停止はプロンプト6のように行う。停止時にはBundleActivatorのstop()メソッドが呼ばれ、ステータスは"RESOLVED"に変わる。

プロンプト6 バンドルの停止

osgi> stop 2
Stop hello1!

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530
2       RESOLVED    hello1_1.0.0

osgi> 

インストール済みのバンドルは、プロンプト7のようにuninstallコマンドでアンインストールできる。

プロンプト7 バンドルのアンインストール

osgi> uninstall 2

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.3.0.v20070530

osgi> 

JSR 291に対する評価

JSR 291は2007年5月08日から21日にかけて最終仕様の承認投票が行われ、賛成多数で通過している。しかしOSGiのオリジナルの仕様との違いが明確ではなく、JSRとして新たに定義する意味がないのではという批判もある。たとえばECの一因であるSun Microsystemsはこの点を問題視して反対票を投じている。また前述のように、Javaプラットフォーム標準のモジュラリティ・サポートとしてはすでにJSR 277が有力候補となっているため、JSR 291の価値を疑問視する声も上がってる。

一方で、JSR 291のExpert GroupがOSGi R4の策定に貢献した結果JSRとの整合性が確保できたとして、その活動を高く評価する声もある。OSGi実装がEclipseのプラグイン機構として採用され広く使われている実績も無視できない。いずれにせよ、Expert Groupとしては他のAPIに対するJSR 291の立ち位置を明確にしていく必要があるだろう。