ポータブルインタセプタ (PI)


このドキュメントを J2SETM ドキュメントバンドルの一部としてダウンロードした場合は、Web サイト http://java.sun.com/j2se/1.4/docs/guide/idl/PI.html を参照して、更新されているかどうかを確認してください。

注: このドキュメントは、高度な知識を持つ CORBA 開発者を対象としています。

JavaTM CORBA Object Request Broker (ORB) は、フック (遮断点) を提供し、ORB サービスはこのフックを使って ORBの通常の実行の流れを遮断することができます。 これらの「ポータブルインタセプタ」は、追加の ORB の動作をプラグインするための機構と、クライアントとサーバ間の通信を変更することによって ORB の動作を変更するための機構を提供します。 このあとのでは、ポータブルインタセプタのさまざまな使い方について説明します。

ポータブルインタセプタのサポートは、CORBA 仕様に最近追加された重要な機能です。 RequestInterceptor を使用すると、ORB が仲介する任意の呼び出しを遮断するポータブル ORB フックを簡単に記述して接続することができます。 IORInterceptor を使用すると、CORBA オブジェクト参照に注釈を付けるためのコードを記述できます。

インタセプタの型

現在、登録できるインタセプタには次の 3 つの型があります。 それぞれの例についてはこのあとので説明します。

Java で ORB 初期化子を登録する

クラス ORBInitializer でインタセプタの登録と ORB の初期化が簡単にできます。

インタセプタにより、ORB サービスは ORB プロセスにアクセスして、効果的に ORB の一部になることができます。 インタセプタは ORB の一部なので、ORB.init が ORB を返すときインタセプタは既に登録済みです。 ORB.init への呼び出しで返された後は、インタセプタはその ORB に登録できません。

ORBInitializers は Java ORB プロパティを経由して登録されます。 ORBInitializer インタフェースを実装する関連オブジェクト ORBInitializer を登録すると、インタセプタが登録されます。 ORB は、登録された ORBInitializer をそれぞれ初期化中に呼び出し、インタセプタを登録するために使用する ORBInitInfo オブジェクトを渡します。

このプロパティ名は以下の形式をとります。

org.omg.PortableInterceptor.ORBInitializerClass.<Service>
<Service> は次のプロパティを実装するクラスの文字列名です。
org.omg.PortableInterceptor.ORBInitializer
名前の衝突を防ぐため、逆方向の DNS 命名規則が使用されます。 たとえば、X 社に初期化子が 3 つある場合、次のプロパティを定義できます。 ORB.init では、org.omg.PortableInterceptor.ORBInitializerClass で始まる ORB プロパティが収集され、それぞれのプロパティから <Service> の部分が抽出され、オブジェクトはクラス名として <Service> 文字列でインスタンスが生成され、そのオブジェクトで pre_init メソッドおよび post_init メソッドが呼び出されます。 例外があっても ORB は無視して処理を行います。

インタセプタのスコープに関する注意

インタセプタ登録時の注意

PortableInterceptor Current (PICurrent)

PortableInterceptor::Current オブジェクト (これ以降 PICurrent と呼ぶ) は、ポータブルインタセプタが、スレッドのコンテキスト情報を要求コンテキストに転送するために使用する Current オブジェクトです。 ポータブルインタセプタは、PICurrent を常に使用する必要はありませんが、インタセプタの遮断点で、クライアントのスレッドコンテキストの情報が必要な場合は、PICurrent を使用してその情報を伝播することができます。 PICurrent を使用すると、ORB のスレッドモデルにかかわらず移植性のあるサービスコードを記述できます。

クライアント側では、この情報に、サービスコンテキストを介してサーバに伝播されるスレッドコンテキストの情報やその他の情報が含まれます。

サーバ側では、この情報に、クライアントから受け取るサービスコンテキストの情報やその他の情報が含まれます。サービスコンテキストの情報は目的のスレッドコンテキストに伝播されます。

PICurrent の取得

PICurrentは、呼び出しを行う前に、ORB::resolve_initial_references ( PICurrent ) の呼び出しによって取得されます。 遮断点で、RequestInfo オブジェクトに対する get_slot オペレーションを実行すると、スレッドスコープから要求スコープに移動された PICurrent に関するデータを取得できます。 PICurrent は、resolve_initial_references を使用して取得することもできますが、この場合はインタセプタのスレッドスコープの PICurrent が取得されます。

要求スコープとスレッドスコープの比較

スレッドスコープの PICurrent (TSC) は、スレッドのコンテキスト内に存在する PICurrent です。 要求スコープの PICurrent (RSC) は、要求に関連付けられている PICurrent です。 クライアント側では、要求の開始時に、スレッドスコープの PICurrent が、スレッドコンテキストから要求スコープの PICurrent に論理的にコピーされ、ClientRequestInfo オブジェクトに接続されます。 サーバ側では、要求スコープの PICurrentServerRequestInfo に接続されてから、要求の処理が行われます。 要求スコープの PICurrent は、receive_request_service_contexts 遮断点のリストが処理されたあとに、スレッドスコープの PICurrent に論理的にコピーされます。 PICurrent のスコープの詳細については、Updated Interceptors specification の 21.4.4.5 節の「Flow of PICurrent between Scopes」を参照してください。


ポータブルインタセプタの例: ロギングサービス

ここでは、ロギングサービスアプリケーションの例について説明します。 このアプリケーションのサンプルコードは、複雑かつ「特殊なケース」を扱うため、非常に複雑になっています。 このサンプルアプリケーションでは以下のシナリオを扱います。

  1. 呼び出しをログに記録するロギングサービス。 クライアントとサーバのどちらもこのロギングサービスを明示的に使用しない

  2. クライアントからサーバに情報を渡す「空の」サービス。 クライアントとサーバは、このサービスを明示的に使用するが、インタセプタを使用してサービスが実装されていることを認識していない

注: 以下の例では、コードを簡単に試してセットアップできるように、ORBInitializer を明示的に登録しています。 一般的にはこのような処理は行いません。 通常、この情報は、アプリケーションの起動時に -D プロパティとして Java 仮想マシンに渡されます。 この方法を使うと、サービス (たとえばロギングサービス) が存在するかどうか、あるいはアプリケーションが明示的に使用するサービス (たとえば AService インタフェース) がインタセプタとして実装されるかどうかという事実にアプリケーションが束縛されなくなります。 たとえば、このロギングサービスを使って MyApp というプログラムを実行するには、ユーザは次のように入力します。

   java -Dorg.omg.PortableInterceptor.ORBInitializerClass.com.x.Logging.LoggingService
     MyApp

このアプリケーションの例では、次のようなインタセプタを使用したロギングサービスアプリケーションの作成方法を示します。

  1. ロギングサービスは単純なクライアントとサーバ側からの発信呼び出しを作成します。

    次の図は、ロギングサービスでの情報の流れを示しています。

    ロギングサービスの説明図

  2. ターゲットがインタセプタと同じ場所に配置されている場合、同じ場所に置かれたロギングサービスは複雑なサーバ側からの発信呼び出しを作成します。

    次の図は、同じ場所に置かれたロギングサービスでの情報の流れを示しています。

    同じ場所に置かれたロギングサービスの説明図

  3. AServiceは、register_initial_referencesresolve_initial_referencesPICurrent、および ServiceContexts を使用して、クライアントコードとサーバコード間でサービスの情報の受け渡しを行います。

    次の図は、AService での情報の流れを示しています。

    AService の説明図

このアプリケーションを作成して実行する場合は、以下の節に示すようにコードを入力し、「アプリケーションのコンパイルと実行」の指示に従ってください。


serviceexample.idl

このファイルは、インタフェース定義言語 (IDL) ファイルで、呼び出しの対象となる任意のオブジェクトの定義と、その任意のオブジェクトに対する呼び出しを実行する 2 つのサービスを含んでいます。


LoggingServiceClientORBInitializer.java

このファイルでは、オブジェクトのクライアントによって使用されるロギングサービスインタセプタを作成して登録します。


LoggingServiceClientInterceptor.java

このインタセプタは、クライアント側の遮断点をログに記録します。 次のコードは、インタセプタ内からほかのオブジェクトの呼び出しを実行する方法と、それらの「発信」呼び出しでの無限回帰を回避する方法を示しています。


LoggingServiceServerORBInitializer.java

このファイルでは、オブジェクトのサーバによって使用されるロギングサービスインタセプタを作成して登録します。 このインタセプタはサーバ側の遮断点だけをログに記録しますが、クライアントとサーバの両方のインタセプタになります。 次のコードは、呼び出されるオブジェクトが、インタセプタが登録された ORB と同じ ORB に置かれている場合に無限回帰を回避する方法を示しています。


LoggingServiceServerInterceptor.java

このインタセプタは、サーバ側の遮断点をログに記録しますが、ClientRequestInterceptor および ServerRequestInterceptor の両方として実装されます。これは、LoggingServiceServerORBInitializer.java の説明で触れたようなケースでの無限回帰を回避するために、「発信呼び出し」サービスコンテキストのデータの一部を (発信呼び出しスロットに加えて) 設定する必要があることを説明するためです。


LoggingServiceImpl.java

このファイルは、ロギングサービスインタセプタがデータを送信する先のロギングオブジェクトの実装です。


AServiceORBInitializer.java

このファイルは、AServiceInterceptor をクライアントとサーバの両方のインタセプタとして作成して登録し、TaggedComponent を IOR に挿入する AServiceIORInterceptor を作成して登録します。さらに、AService によって提供されるサービスをアプリケーションが明示的に制御するために使用するローカルオブジェクトを作成します。 クライアントが org.omg.CORBA.ORB.resolve_initial_references を使用してこのローカルオブジェクトを取得できるように、このローカルオブジェクトは初期サービスとして ORB に登録されます。


AServiceImpl.java

このファイルは、クライアントとサーバントのコードがサービスと通信するために明示的に使用するオブジェクトを含んでいます。 クライアントがサービスに対する begin() を呼び出すと、サービスに固有の ServiceID が、このサービスによって予約されている TSC PICurrent スロットに置かれます。 クライアントがサービスに対する end() を呼び出すと、サービスが有効になっていないことを示すために、サービスによって TSC スロットが無効な値に設定されます。 サーバントは、verify() メソッドを使用して、ServiceID がクライアント側からサーバ側に渡されたかどうかを調べます。


AServiceInterceptor.java

このインタセプタは、クライアント側の AService 情報をサービス側に渡すための準備を行います。

クライアント側では、AService.begin() が呼び出されると、send_request(ri) ポイントが RSC スロット内のサービス ID を確認します。 この場合、send_request(ri) は、サービス ID の値を org.omg.CORBA.ServiceContext に挿入し、そのサービスコンテキストを呼び出しで渡されるデータに追加します。

サーバ側では、receive_request_service_context(ri) が、そのサービスコンテキストの存在を確認します。 サービスコンテキストが存在している場合、receive_request_service_context(ri) は、ServiceContext からサービス ID 値を抽出し、RSC スロットをその値に設定します。 サーバントの実行中は、RSC スロットの値を TSC スロット内で使用できます。


AServiceIORInterceptor.java

このファイルは、TaggedComponent を IOR に追加します。


ArbitaryObjectImpl.java

このファイルは、ArbitraryObject IDL インタフェースのサーバおよび実装です。 この IDL インタフェースオペレーションの実装では、クライアントからサーバントへの AService.begin() を使用したエンドツーエンドデータの受け渡しを説明するために、AServiceImpl.verify() メソッドを明示的に呼び出しています。


Client.java

これは、ArbitraryObject に対するメソッドを呼び出すクライアントです。 このクライアントは、AService のコンテキストの内部と外部で、それらの呼び出しをいくつか実行します。 クライアントは、ロギングインタセプタの存在を認識しません。ただし、前の例のように LoggingServerClientORBInitializer を明示的に登録します。


ColocatedServers.java

このファイルは、ArbitraryObject および LoggingService の両方を同一の ORB 内で実行するサーバです。 つまり、これらのオブジェクトは「同じ場所に置かれています」。

このサーバは、LoggingServiceServerInterceptor 内のコードを試すために、このような方法で作成されています。このコードは、インタセプタが、同じ ORB 内に置かれている複数のオブジェクトに対する呼び出しを実行するときに、無限回帰を回避するために追加の処理を実行する必要があることを示しています。


アプリケーションのコンパイルと実行

このアプリケーションをコンパイルして実行するには
.
.
.
.
.
.

関連項目:
ORBInitInfo
org.omg.PortableInterceptor パッケージ


コメントの送付先: JavaIDL@eng.sun.com.