レベル: 中級 Rajeev Hathi, Senior Software Consultant Naveen Balani, Software Architect, IBM
2008年 10月 30日 Java™ クラス・コンポーネントを OSGi (Open Services Gateway initiative) バンドルとして開発、作成、パッケージ化し、Apache Felix ランタイム環境にデプロイしてください。すると、Felix シェル・コマンドを使用してバンドルの起動と停止、そして動的な更新を実行できるようになります。
はじめに
連載第 1 回目のこの記事では、クライアント・サイドとサーバー・サイドのコンポーネントを使って注文用アプリケーションを開発し、これらのコンポーネントを OSGi バンドルとしてパッケージ化します。このアプリケーションではクライアントが注文を処理するためにサービス・コンポーネントを呼び出すと、サービス・コンポーネントのメソッドが注文を処理して注文 ID を出力します。この記事を読み終えれば、Apache Felix の概念と機能を適用して Java コンポーネント・クラスを OSGi バンドルとして作成し、パッケージ化できるようになっているはずです。
システム要件
この記事のサンプル・コードを実行するには、お使いのマシンに必ず以下のソフトウェアをインストールして、セットアップしてください。
- Java 5 以降
- Ant ビルド・ツール
- Apache Felix バイナリー・ディストリビューション 1.0.4
次に、以下の環境変数を設定します (一例として、ANT_HOME=C:\apache-ant-1.7.0 と設定します)。
- JAVA_HOME (Java 用)
- ANT_HOME (Ant 用)
続いて PATH 環境変数に以下の内容を追加します。
- JAVA_HOME\bin
- ANT_HOME\bin
OSGi
OSGi は、動的に Java アプリケーションをモジュールとして定義し、そのモジュールをネットワーク上でやりとりするための仕様です。従来、Java アプリケーションは JAR バンドルとしてモジュール化されていますが、JAR ファイルを扱う際には以下の限界があります。
- JAR バンドルはクラスパス環境変数によって解決されるため、JAR 依存関係を管理するには堅牢なフレームワークとは言えません。
- JAR バンドルのバージョン管理はできません。したがって、JAR バンドルの作成あるいは変更の履歴を辿ることができません。
- コードの変更に対応して JAR ファイルを実行時に動的に更新するフレームワークがありません。
上記の問題に対処するには、OSGi フレームワークを使用することができます。OSGi は、Java のモジュール・システムを再定義するからです。OSGiベースのシステムには、従来の JAR モジュールに勝る以下の利点があります。
- OSGi が提供する堅牢な統合環境では、バンドルをサービスとして公開し、他のバンドルが使用できるようにエクスポートすることができます。
- OSGi は、あらゆる新しいデプロイメントに際してバンドルのバージョン管理を行います。そのため、バンドルの作成および変更の履歴を追跡することが可能です。
- OSGi では、コードの変更に応じて常に、実行時にバンドルを動的に更新することができます。
現在、以下の 3 つが OSGi の実装として知られています。
- Equinox
- Knopflerfish
- Felix
この記事では、Felix を OSGi コンテナーとして使用する例を説明します。連載全体では以下のトピックを取り上げます。
- 第 1 回では、OSGi API を使用してコンポーネントを開発する方法を説明します。
- 第 2 回では OSGi コンテナー内で Spring を使用し、OSGi API 依存関係をコンポーネント・クラスからなくすことによって POJO (Plain Old Java Object) にします。この方法の利点は、開発者がコンポーネント・クラス内のビジネス・メソッドの作成だけに専念できるようになり、コンポーネントのライフサイクルの処理は Spring 構成ファイルに任せられることです。
注文用アプリケーション
それでは早速、Felix ベースの OSGi フレームワークを使用して注文用アプリケーション・バンドルの作成に取り掛かります。このアプリケーションには、OrderClient.java (クライアント・サイド) と OrderService.java (サーバー・サイド) という 2 つのコンポーネントがあります。クライアント・コンポーネントは client.jar としてバンドルし、サーバー・コンポーネントは order.jar としてバンドルします。まずは OrderClient クラスを見てください。
リスト 1. クライアント・コンポーネント、OrderClient
public class OrderClient implements BundleActivator {
private ServiceTracker orderTracker;
private OrderService orderService;
public void setService(OrderService orderService) {
this.orderService = orderService;
}
public void removeService() {
this.orderService = null;
}
public void start(BundleContext context) throws Exception {
orderTracker =
new ServiceTracker(context, OrderService.class.getName(), null);
orderTracker.open();
OrderService order = (OrderService) orderTracker.getService();
if (order == null) {
System.out.println("Order service not available");
} else {
order.processOrder();
}
}
public void stop(BundleContext context) {
System.out.println("Bundle stopped");
orderTracker.close();
}
}
|
リスト 1 を見るとわかるように、client.jar バンドルが起動されると、OrderClient クラスが OrderService コンポーネントの processOrder メソッドを呼び出し、orderID を出力します。このクラスが実装する BundleActivator インターフェースには 2 つのコールバック・メソッド、start() と stop() があります。Felix コンテナーはクライアント・バンドルの起動時、停止時に、実装された start() メソッドと stop() メソッドをそれぞれ呼び出します。
start() メソッドを詳しく見てみると、start() メソッドで最初に取得するのは ServiceTracker クラスの参照です。このクラスはファクトリー・クラスだと思ってください。次に、このファクトリー・クラスの getService メソッドを呼び出して、このクラスからサービス参照を取得します。ServiceTracker を構成するパラメーターは、バンドルのコンテキストと OrderService クラスの名前です。
リスト 2. OrderService の実装
public class OrderServiceImpl implements OrderService, BundleActivator {
private ServiceRegistration registration;
public void start(BundleContext context) {
registration =
context.registerService(OrderService.class.getName(), this, null);
System.out.println("Order Service registered");
}
public void stop(BundleContext context) {
System.out.println("Order Service stopped");
}
public void processOrder() {
System.out.println("Order id: ORD123") ;
}
}
|
サーバー・サイドの order.jar ファイルに含まれるコンポーネントは、OrderService インターフェースと OrderServiceImpl クラスの 2 つです。このインターフェースには抽象メソッド、processOrder があり、このメソッドは OrderServiceImpl クラスによって実装されます。このクラスは、Felix コンテナーが order.jar バンドルを起動、停止するために呼び出す BundleActivator インターフェースも実装します。start() メソッドはレジストリーに OrderService コンポーネントを登録して、クライアント・バンドルが使用できるようにします。登録とは、他のバンドルが使用できるようにオブジェクトをエクスポートすることと同じです。
マニフェストによる情報伝達
ここで疑問となるのは、クライアント・バンドルはどうやって登録されたサービス・バンドルを認識するのかという点です。サービス・バンドルを認識するための情報は、マニフェスト・ファイルを使って伝達され、マニフェスト・ファイルの中で、インポートおよびエクスポート・パッケージの一部としてバンドルの参照を指定します。通常、クライアント・バンドルのマニフェストはサービス・コンポーネント・パッケージをインポートする一方、サービス・バンドルのマニフェストはこのバンドル自体のパッケージをエクスポートします。つまり、例えばバンドル A がバンドル B のパッケージをインポートするときには、バンドル B はその固有のパッケージをエクスポートする必要があるということです。適切なインポートとエクスポートの定義がなければ、この情報伝達は失敗します。
リスト 3. クライアントのマニフェスト・ファイル
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service Client
Bundle-SymbolicName: orderclient
Bundle-Version: 1.0.0
Bundle-Activator: order.client.OrderClient
Import-Package: org.osgi.framework, org.osgi.util.tracker, order
|
リスト 4. サービスのマニフェスト・ファイル
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service
Bundle-SymbolicName: orderservice
Bundle-Version: 1.0.0
Export-Package: order
Bundle-Activator: order.impl.OrderServiceImpl
Import-Package: org.osgi.framework
|
この注文用アプリケーションの場合、client.jar バンドルのマニフェストには Import-Package: org.osgi.framework, org.osgi.util.tracker, order というエントリーがあります。このエントリーが事実上、意味していることは、コアとなる OSGi パッケージ、そして OrderService パッケージをクライアント・バンドルがインポートするということです。同様に、order.jar バンドルのマニフェストには Export-Package: order というエントリーがあり、このバンドルがバンドル自体をパッケージとしてエクスポートしてクライアントが使用できるようにすることを意味します。このようにインポートとエクスポートが明示的に宣言されていなければ、OSGi はランタイム・エラーをスローします。
マニフェスト・ファイルには、その他の情報としてバンドル・アクティベーター・クラスの名前なども含まれます。アクティベーター・クラスの役割は、バンドルの start() メソッドと stop() メソッドを呼び出すことです。この例では、client.jar バンドルのアクティベーター・クラスは order.jar バンドルの OrderClient および OrderService となります。
デプロイメント
バンドルをデプロイして操作する前に、以下のステップを行います。
- ルートである C:\osgi フォルダーの配下に図 1 に示すディレクトリー構造を作成し、この記事でこれまでに説明したコンポーネントを以下のように配置してください。
- Java コードは、該当するパッケージ・フォルダー (クライアントとサービスの両方) に配置します。
- マニフェスト・ファイルは、該当する META-INF フォルダー (クライアントとサービスの両方) に配置します。
図 1. コードのディレクトリー構造
次のステップは、これらのバンドルをデプロイすることです。Felix OSGi コンテナーを使用して、以下のステップに従ってクライアント・バンドルとサービス・バンドルをデプロイしてください。
- サービス・フォルダー内に置かれた ANT を使用して build.xml を実行します。
- クライアント・フォルダー内に置かれた ANT を使用して build.xml を実行します。
上記のビルド・ファイルを実行すると、client/bin フォルダーと service/bin フォルダーにそれぞれ client.jar バンドル、order.jar バンドルが作成されます。
- Microsoft® Windows® のコマンド・プロンプトで startfelix.bat を実行し、Felix ランタイムを起動します。
Felix ランタイムを起動するたびに、プロファイル名を入力するよう求めるプロンプトが出されます。プロファイル名はいわば、プロジェクト名のようなものです。プロジェクト・プロファイルには任意の名前を指定して構いません。以降の Felix ランタイムの起動時に、前に入力したプロファイル名と同じ名前を指定すると、Felix はそのプロジェクト名に関連するインストール済みのバンドルをすべてロードします。新しいプロファイル名を指定した場合には、バンドルを再度、明示的にインストールする必要があります。
- Felix シェルで以下のコマンドを入力してバンドルをインストールします。
install file:service/bin/order.jar
install file: client/bin/client.jar
start service_bundle_id
start client_bundle_id
バンドルの ID を示すには、ps コマンドを実行してください。バンドルを起動する際は、まずサービス・バンドルを起動してから、クライアント・バンドルを起動する必要があります。それぞれのバンドルが起動すると、以下の出力が表示されます (図 2 を参照)。
図 2. プログラムの出力
バンドルは更新することもできます。それには、Felix シェルで update bundle_id コマンドを実行してください。すると、バンドルが実行時にオンザフライで更新されます。
まとめ
この記事では、OSGi フレームワークの機能と概念を簡単に説明した後、このフレームワークを使用して動的 JAR バンドルを作成する方法を例を用いて説明しました。そして、コンポーネントを OSGi バンドルとして作成してパッケージ化する方法と、Felix ランタイム環境でその OSGi バンドルを実行する方法を学びました。さらに、バンドル間の情報伝達用インターフェースとしての役割を担うバンドルのマニフェスト・ファイルの作成についても取り上げました。
OSGi は、JAR バンドルを作成、管理する新たな方法を提供します。連載第 2 回では、Spring フレームワークが OSGi 環境で OSGi に代わってバンドルを管理する仕組みについて説明します。お楽しみに。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| OSGi Order Application | osgi_orderapp.zip | 6KB | HTTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
- IBM 製品の評価版をダウンロードして、DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を使ってみてください。
議論するために
著者について  | 
|  | Rajeev Hathi は、J2EE プラットフォームのソフトウェア・コンサルタントです。J2EE をベースとしたアプリケーションの設計を専門とする彼は、Java および J2EE 技術分野 (Web、EJB、Architect) での SUN 認証を獲得しています。IBM developerWorks には Ajax、Web サービス、DB2、XML 関連の記事で貢献しています。さらに、Java 6 の適用方法に関する本『Hands on Web Services』の共著者でもあります。彼が拠点とするのはインドのムンバイで、スポーツ観戦とロックを聴くことを趣味としています。 |
 | 
|  | Naveen Balani は、IBM India Software Labs (ISL) のアーキテクトで、ISLでは WebSphere Business Services Fabric の設計および開発作業のリーダーを務めています。新しい技術の調査に積極的な彼は、IBM developerWorks ではお馴染みの寄稿者でもあり、今まで Web サービス、ESB、JMS、SOA、アーキテクチャー、オープンソース・フレームワーク、セマンティック Web、J2ME、パーベイシブ・コンピューティング、Spring、Ajax、そしてさまざまな IBM 製品についての記事を書いています。また、『Beginning Spring Framework 2』、『Getting Started with IBM WebSphere Business Services Fabric V6.1』の共著者でもあります。 |
記事の評価
|