サーバサイドにおけるOSGiの概要
Pages: 1, 2, 3

OSGiの稼動部品:環境とバンドル

OSGi環境は、前述の多くの機能を使用するために必要なブラックボックスを提供します。ここで「ブラックボックス」という言葉を使用するのは、 Java EEコンテナがベンダの領域であるように、環境の作成はOSGiベンダ/プロバイダの領域であるからです。開発者やアーキテクトの方にとっては、OSGi の背後にある展開モデルやプログラミングモデルが一番の関心事でしょう。これらのモデルは、Java EEのようにあらゆるOSGi環境で同じように応用できます。

Java EEコンテナからSpringなどの軽量なフレームワークに移行している一部の企業は、最後に挙げたJava EEコンテナとOSGi環境の比較に抵抗を感じるかもしれません。しかし、この比較は、OSGiの機能とSpringの機能の統合に関係があり、実際の仕 事に役に立つ内容です。説明を読み進めるうちに、OSGiのメリットをSpringプロジェクトで活かす方法が分かってくるでしょう。OSGiでは、 環境実装実行時コンテナ、および フレームワークが同義的に使用されることがよくあるので注意が必要です。これらの用語には柔軟に対応してください。OSGiベンダ/プロバイダによって配布される同じソフトウェアピースのことを指す場合もあります。

OSGi環境について学び始めると、スマートフォンなどの小さな機器で使用される環境がデスクトップアプリケーションやサーバサイドプロジェクトの 管理に同じように使用されるという事実に驚くかもしれません。このことは、OSGiの展開/プログラミングモデルをさまざまなシナリオで同じように利用で きるということを示しています。OSGiのこうした特徴が最も具体的な形で示されているのが「バンドル」です。バンドルは、開発者やアーキテクトが大半の 時間直接扱うことになる要素なので、バンドルの概念を把握しておくことはOSGiを理解するうえで必要不可欠なステップです。ここでは、実際に例を挙げな がらバンドルの概念について簡単に説明します。

バンドル(またはモジュール)とは、OSGiで使用されるパッケージ形式です。Javaクラスやリソースとともに基本的なOSGi環境で使用される その他の処理命令を格納したもので、JARファイルによく似た構造を持つパッケージになっています。ここで、「JARファイルと同じようなパッケージ方式 であるなら、OSGiバンドルとJARファイルのどこが違うのか」という疑問が生じるでしょう。あるいは、さらに掘り下げて「OSGiバンドルのJAR形 式にするために、既存のすべてのアプリケーションのJARファイルを再パッケージしなければならないのはなぜか」という疑問が生じるかもしれません。

クラス ローダー グラフ
図1. クラス ローダー グラフ、多くのバンドルに含まれる一部のクラスからOSGiが作成

結局、OSGiバンドルJARファイルの内容(Javaクラスと他のアプリケーションリソースで構成された単なるOSGiモジュール)は、従来の Javaクラスパスでは利用できません。これらのファイルはOSGi環境に依存しているため、それぞれのOSGiバンドルJARファイルに格納されている 基本となるすべてのクラスとリソースの間の依存関係を解決するための、ある種の クラス ローダー グラフが作成されます。

この クラス ローダー グラフのコンセプトはいくつかの理由から特殊です。まず、アプリケーションの実行時の任意の時点でロード されるJavaクラスとリソースの量を制限します。また、グラフモデルに依存するため、OSGi環境内で稼動する任意のアプリケーションは、クラスの依存 関係を満たすために必要に応じてブランチを自動的に作成、結合、および廃棄し、最初に述べたような機能を動的にインストール、開始、停止、更新、およびア ンインストールできるようになります。同様に重要な点として、OSGiバンドルはプレーンなJavaクラスとリソースで構成されているため、OSGi環境 は基礎的なアプリケーションロジックをまったく把握していません。このため、Eclipse IDEプラグイン、XML構文解析ツール、コンソールベースのアプリケーション、サーブレット、またはその他のバリエーションのOSGiバンドルが誕生す る可能性があります。

こうした背景情報を学んだところで、いよいよ実際のOSGiバンドルについて見ていきましょう。ここではOSGiバンドルの概要を説明するために、 できる限りシンプルな例を取り上げます。まずこの例を理解し、そのうえでログパッケージやサーブレットエンジン、その他のバリエーションなど、企業向けの 複雑なバンドルに同じ原則を適用する方法について検討してみます。

ここで例示するバンドルは、航空会社サービス用のアプリケーションです。このバンドルは、任意の都市へのフライト空席状況を取得する他のOSGiバンドルで利用できます。

package intro.carrier;

import java.util.Properties;

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

import intro.carrier.service.FlightService;

/**
 * This class implements a simple bundle that uses the bundle
 * context to register international flight availability service
 * with the OSGi framework. The flight service interface is
 * defined in a separate class file and is implemented by an
 * inner class.
**/
public class Activator implements BundleActivator
{
    /**
     * Implements BundleActivator.start(). Registers an
     * instance of a flight service using the bundle context;
     * attaches properties to the service that can be queried
     * when performing a service look-up.
     * @param context the framework context for the bundle.
    **/
    public void start(BundleContext context)
    {
        Properties props = new Properties();
        props.put("Seating", "International");
        context.registerService(
            FlightService.class.getName(), new FlightImpl(), props);
    }

    /**
     * Implements BundleActivator.stop(). Does nothing since
     * the framework will automatically unregister any registered services.
     * @param context the framework context for the bundle.
    **/
    public void stop(BundleContext context)
    {
        // NOTE: The service is automatically unregistered.
    }

    /**
     * A private inner class that implements a flight service;
     * see FlightService for details of the service.
    **/
    private static class FlightImpl implements FlightService
    {
        // The set of cities contained in the flight service
        String[] c_flight =
            {"mexico city", "paris", "london", "sao paulo", "toronto"};

        /**
         * Implements FlightService.checkAvailability(). Determines
         * if the passed in city is available 
         * @param flight the flight to be checked.
         * @return true if the flight seating is available,
         *         false otherwise.
        **/
        public boolean checkAvaiability(String flight)
        {
            flight = flight.toLowerCase();

            for (int i = 0; i < c_flight.length; i++)
            {
                if (c_flight[i].startsWith(flight))
                {
                    return true;
                }
            }
            return false;
        }
    }
}

まず、さまざまなorg.osgi.frameworkクラスをインポートします。この作業は、ほぼあらゆるOSGiバンドルで実行される基本的な 作業です。次に、これもOSGiの中心である2つの初期メソッド、startとstopを宣言します。名前から想像できるように、このメソッドはOSGi バンドルを基盤環境から登録または登録解除するために呼び出します。残りのコードは、サービスロジックとして使用する具体的なインナークラスです。手の込 んだ仕掛けは何もありません。いくつかのハードコード値だけで、次のインタフェースに目的と依存関係を指定します。

package intro.carrier.service;
/**
 * A simple service interface that defines a flight service.
 * A flight service simply verifies the existence of seating.
**/
public interface FlightService
{
    /**
     * Check for the availability of a flight.
     * @param flight the flight to be checked.
     * @return true if the flight seating is available,
     *         false otherwise.
    **/
    public boolean checkAvailability(String flight);
}

Javaコードに関してはこれですべてです。次に、前述のJavaクラスとともに指定する必要のあるOSGi記述子について説明します。

Bundle-Name: International Flights
Bundle-Description: A bundle that registers International Flight service
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: intro.carrier.Activator
Export-Package: intro.carrier.service
Import-Package: org.osgi.framework

パラメータの名前と記述から内容はすぐ分かります。Bundle-Vendorパラメータは展開に使用されるOSGi実装を示します。この例の場 合、Apache Software FoundationのFelixという名前のOSGi実装であることを示しています。Bundle-Versionフィールドでは、単に最初のバンドル 番号である1.0.0が示されています。

残りのフィールドは少し注意が必要です。Bundle-Activatorは実際のアクティベーションロジック(startおよびstopメソッ ド)を格納しているクラスを示し、Export-Packageは他のOSGiバンドルが利用できるバンドル内のパッケージを指定します。この例の場合 は、サービスパッケージへのアクセスが許可されるように指定されています。最後のImport-Packageは、バンドルを正常に展開するためにロード する必要のある依存関係を指定します。

Javaコードのコンパイルは、コンパイル対象のクラスパスでOSGi実装を使用できる場合、他のJavaソースファイルと同じ方法で実行されま す。OSGiバンドルの実際の作成作業は、Java SEに含まれている標準のjarユーティリティを使用して行われます。最終的に作成されるパッケージのOSGiバンドルは、次のようなディレクトリ構造に なっています。

+-|
  |
  +-META-INF-+
  |          |+MANIFEST.MF
  |
  |
  +-intro/carrier-+
  |               |+Activator$1.class
  |               |+Activator$FlightImpl.class
  |               |+Activator.class
  |
  |
  +-intro/carrier/service-+
                          |+FlightService.class

やや長く機械的なプロセスですが、これは例として取り上げているアプリケーションで使用される残りのバンドルを示していないためです。必要に応じ て、多数のサンプルOSGiバンドルの作成を簡素化する自動ビルドスクリプトを収録したサンプル ダウンロード コードを参照することができます。OSGiバンドルのパッケージ化作業は、JARファイルと同様、ほとんど一度だけの作業で済みます。たいていの場合、こ の作業はサードパーティプロバイダが行います。OSGiバンドルの膨大なリポジトリがすでに包括的に公開されているため、プロジェクトではJMXやRMI からXMLRPCまでのあらゆるコードを利用できます。例えば、 Oscar Bundle Repositoryなどのリポジトリがあります。

OSGiバンドルについて理解できたところで、では実際にバンドルを使用するアプリケーションを実行および展開してみましょう。

Pages: 1, 2, 3

Next Page »