オブジェクトアダプタは、オブジェクト参照を使用する要求と適切なコードを接続して、その要求にサービスを提供するメカニズムです。ポータブルオブジェクトアダプタ (POA) は、CORBA 仕様によって定義された特別な種類のオブジェクトアダプタです。POA は次の目標を満たすように設計されています。
このドキュメントでは、Java 2 Platform, Standard Edition での POA の使用法の概要について説明します。POA の詳細については、CORBA 2.3.1 仕様の第 11 章を参照してください。
POA を作成して使用するための手順は、開発する特定のアプリケーションによって異なります。POA のライフサイクルでは、通常、次の手順を実行します。
ステップ 1: ルート POA の取得
最初の手順は、1 番目の POA の取得です。この POA は「ルート POA」と呼ばれます。ルート POA は、ORB によって管理され、ORB 初期化インタフェースを使用するアプリケーションに「RootPOA」という初期オブジェクト名で提供されます。
ルート POA オブジェクトを取得し、それを POA にキャストするコードの例を次に示します。
ORB orb = ORB.init( args, null ); POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));ステップ 2: POA のポリシーの定義
ポータブルオブジェクトアダプタ (POA) は、複数の ORB 実装で使用できるオブジェクトアダプタを提供するために設計されており、異なるベンダーの実装を扱う場合も書き直す必要がないようになっています。
POA は、少なくともクライアントの立場からは持続オブジェクトが可能になるようにしています。つまり、サーバーが物理的に何度再起動されても、そのクライアントが関係する範囲では、これらのオブジェクトは常に稼働しており、オブジェクトに格納されたデータ値が維持されています。
POA を使用すると、オブジェクトの実装者は、オブジェクトの識別、状態、記憶領域、およびライフサイクルに関してより多くの制御を行うことができます。POA は、使用されるポリシーやデフォルト値を定義しないで作成できます。ルート POA にはデフォルトで次のポリシーが定義されています。
次のコードは、RMI-IIOP を使った POA の例でのポリシーの設定方法を示しています。
Policy[] tpolicy = new Policy[3]; tpolicy[0] = rootPOA.create_lifespan_policy( LifespanPolicyValue.TRANSIENT ); tpolicy[1] = rootPOA.create_request_processing_policy( RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY ); tpolicy[2] = rootPOA.create_servant_retention_policy( ServantRetentionPolicyValue.RETAIN);
次に各ポリシーについて簡単に説明します。POA ポリシーの詳細は、CORBA/IIOP 2.3.1 仕様の第 11 章「Portable Object Adapter」を参照してください。
このポリシーは、作成済みの POA とともに使用されるスレッドモデルを指定します。デフォルトは ORB_CTRL_MODEL
です。
ThreadPolicyValue
には、次の値を指定できます。
ORB_CTRL_MODEL
- ORB は ORB 制御 POA の要求をスレッドに割り当てます。SINGLE_THREAD_MODEL
- 単一スレッド POA の要求が順に処理されます (注: このポリシーは、Sun の J2SE v.1.4.1 以降に含まれる ORB ではサポートされていない)。このポリシーは、作成済みの POA 内で実装されるオブジェクトのライフタイムを指定します。デフォルトは TRANSIENT
です。
LifespanPolicyValue
には、次の値を指定できます。
TRANSIENT
- その POA で実装されたオブジェクトは、それらが最初に作成される POA インスタンスよりも長く存続することはできません。PERSISTENT
- その POA で実装されたオブジェクトは、それらが最初に作成されるプロセスよりも長く存続できます。このポリシーは、作成済みの POA 内で起動されるサーバントが一意のオブジェクト ID を持つ必要があるかどうかを指定します。デフォルトは UNIQUE_ID
です。
IdUniquenessPolicyValue
には、次の値を指定できます。
UNIQUE_ID
- その POA を使用して起動されるサーバントはオブジェクト ID を 1 つだけ持つ。MULTIPLE_ID
- その POA を使用して起動されるサーバントは 1 つまたは複数のオブジェクト ID を持つことができる。このポリシーは、作成済みの POA 内のオブジェクト ID がアプリケーションまたは ORB のどちらによって生成されるかを指定します。デフォルトは SYSTEM_ID
です。
IdAssignmentPolicyValue
には、次の値を指定できます。
USER_ID
- その POA を使って作成されたオブジェクトには、アプリケーションによってだけオブジェクト ID が割り当てられます。SYSTEM_ID
- その POA を使用して作成されるオブジェクトには、POA によって一意のオブジェクト ID が割り当てられる。この POA に PERSISTENT
ポリシーも指定されている場合は、割り当てられたオブジェクト ID が、同じ POA のすべてのインスタンス生成にわたって一意である必要があります。このポリシーは、作成された POA がアクティブなサーバントを Active Object Map に保存するかどうかを示します。デフォルトは RETAIN
です。
ServantRetentionPolicyValue
には、次の値を指定できます。
RETAIN
- その POA がアクティブなサーバントを Active Object Map に保存することを示します。NON_RETAIN
- サーバントが POA によって保存されないことを示します。このポリシーは、作成された POA がどのように要求を処理するかを示します。デフォルトは USE_ACTIVE_OBJECT_MAP_ONLY
です。
RequestProcessingPolicyValue
には、次の値を指定できます。
USE_ACTIVE_OBJECT_MAP_ONLY
- オブジェクト ID がアクティブオブジェクトマップ内で見つからない場合、クライアントに OBJECT_NOT_EXIST
例外が返されます。RETAIN
ポリシーも必須です。USE_DEFAULT_SERVANT
- オブジェクト ID がアクティブオブジェクトマップ内で見つからない場合、または NON_RETAIN
ポリシーが存在する場合、set_servant
オペレーションを使ってデフォルトサーバントが POA に登録されていれば、要求はデフォルトサーバントにディスパッチされます。USE_SERVANT_MANAGER
- オブジェクト ID がアクティブオブジェクトマップ内で見つからない場合、または NON_RETAIN
ポリシーが存在する場合、set_servant_manager
オペレーションを使ってサーバントマネージャーが POA に登録されていれば、サーバントマネージャーがサーバントを検索または起動するか、あるいは例外を発生させる。このポリシーは、作成済みの POA でサーバントの暗黙的な起動がサポートされるかどうかを指定します。デフォルト値は IMPLICIT_ACTIVATION
です。
ImplicitActivationPolicyValue
には、次の値を指定できます。
IMPLICIT_ACTIVATION
- サーバントの暗黙的な起動を示す。この値を指定するときは、SYSTEM_ID
と RETAIN
ポリシーが設定されている必要があります。NO_IMPLICIT_ACTIVATION
- サーバントの暗黙的な起動を行わないことを示す。アプリケーション開発者は、新しい POA を作成することによって、新しい POA 用に選択した特定のポリシーを宣言し、異なるアダプタアクティベータおよびサーバントマネージャー (これらは、必要時の POA の起動とサーバントの起動を行うために POA が使用するコールバックオブジェクト) を提供できます。オブジェクト ID は POA に対して相対的に解釈されるため、アプリケーション開発者は、新しい POA を作成することによってさらにオブジェクトの名前空間の区分けも行うことができます。また、新しい POA を作成すると、開発者は、複数のオブジェクトのセットに対する要求の処理を個別に制御できます。
POA は、親の POA に対する create_POA オペレーションを使用して、既存の POA の子として作成されます。新しい POA を作成するには、次の情報を渡します。
childPOA
という名前を付ける。次のコードは、持続サーバーを使った Hello World の例での POA の作成方法を示します。
// Create a POA by passing the Persistent Policy POA persistentPOA = rootPOA.create_POA("childPOA", null, persistentPolicy );
各 POA オブジェクトには POAManager
オブジェクトが関連付けられます。POAManager オブジェクトは、POA に対する要求をキューに入れるか破棄するかといった、関連 POA の処理状態を制御します。POAManager
は、POA を停止することもできます。POA マネージャーには、1 つまたは複数の POA オブジェクトを関連付けることができます。
POAManager
には、次の状態を指定できます。
これらの状態の詳細については、 POAManagerOperations
の javadoc を参照してください。
POA マネージャーは、作成時に自動的に起動されません。次のコードは、持続サーバーを使った Hello World の例での POAManager の起動方法を示します。この方法で POA マネージャーを起動しないと、POA マネージャーはデフォルトでは HOLD
状態になっているため、Servant
に対するすべての呼び出しがハングアップしてしまいます。
// Activate PersistentPOA's POAManager. Without this step, // all calls to Persistent Server will hang because POAManager // will be in the 'HOLD' state. persistentPOA.the_POAManager().activate( );
次の説明は、CORBA 仕様のセクション 11.2.5 から引用したものです。
CORBA オブジェクトは、アクティブなサーバントに関連付けられる場合と関連付けられない場合があります。POA に RETAIN
ポリシーが定義されている場合、サーバントとサーバントに関連付けられているオブジェクト ID が、適切な POA のアクティブオブジェクトマップに入力されます。このような起動は、次のどれかの方法で実行できます。
activate_object
オペレーションまたは activate_object_with_id
オペレーションを使用して、個々のオブジェクトを明示的に起動する。set_servant_manager
を使用してこのサーバントマネージャーを登録する。IMPLICIT_ACTIVATION
ポリシーが有効でかつ言語バインディングで次のようなオペレーションが許可されている状況では、サーバーアプリケーションが、起動されていない (つまりオブジェクト ID が関連付けられていない) サーバントの参照を取得しようとしたときに、POA がオブジェクトを暗黙的に起動できる。USE_DEFAULT_SERVANT
ポリシーも有効になっている場合、サーバーアプリケーションは、オブジェクト ID にかかわらず、1 つのサーバントを起動することによって未知のオブジェクトを起動するように POA に指示します。サーバーアプリケーションは、set_servant
を使用してこのサーバントを登録します。
POA に NON_RETAIN
ポリシーが定義されている場合、POA は、すべての要求に対して、デフォルトのサーバントまたはサーバントマネージャーを使用してアクティブなサーバントを探すことができます。POA から見ると、サーバントは、1 つの要求の処理中だけアクティブになっています。POA は、サーバントとオブジェクトの関連付けをアクティブオブジェクトマップに入力しません。
RMI-IIOP テクノロジを使用している実装は、その実装をインタフェースに関連付けるために委譲 (「Tie モデル」と呼ばれる) を使用します。実装のインスタンスを作成したときは、そのインスタンスを CORBA インタフェースに関連付けるために Tie オブジェクトを作成する必要もあります。次のコードは、POA ポリシーが USE_ACTIVE_OBJECT_MAP_ONLY
の場合に Tie を起動する方法を示しています。このサンプルコードは、RMI-IIOP を使った POA の例で使用されているものです。
_HelloImpl_Tie tie = (_HelloImpl_Tie)Util.getTie( helloImpl ); String helloId = "hello"; byte[] id = helloId.getBytes(); tPOA.activate_object_with_id( id, tie );
CORBA 仕様には、オブジェクト参照の作成 (セクション 11.2.4)、オブジェクトの起動 (セクション 11.2.5)、および要求の処理 (セクション 11.2.6) に関する詳しい説明が記載されています。詳細は、「CORBA 2.3.1 仕様」を参照してください。
ステップ 6: オブジェクト参照の作成オブジェクト参照はサーバーで作成されます。作成したオブジェクト参照はクライアントにエクスポートできます。オブジェクト参照は、オブジェクトの識別情報をカプセル化し、さらにオブジェクトに関連付けられているサーバーと POA を識別して探すために ORB が必要とする情報をカプセル化します。参照は、次のいくつかの方法で作成されます。
次の例は、持続サーバーを使った Hello World の例で使用されているものです。この例では、servant_to_reference
オペレーションを使用して、起動したサーバントを対応するオブジェクト参照にマッピングします。
// Resolve Root Naming context and bind a name for the // servant. org.omg.CORBA.Object obj = orb.resolve_initial_references( "NameService" ); NamingContextExt rootContext = NamingContextExtHelper.narrow( obj ); NameComponent[] nc = rootContext.to_name( "PersistentServerTutorial" ); rootContext.rebind( nc, persistentPOA.servant_to_reference( servant ) );
次の例は、RMI-IIOP を使った POA の例で使用されているものです。この例では、次のコードによって直接参照を作成します。そのために、抽象オブジェクトを実体化しますが、そのオブジェクトをアクティブなサーバントには関連付けません。
// Publish the object reference using the same object id // used to activate the Tie object. Context initialNamingContext = new InitialContext(); initialNamingContext.rebind("HelloService", tPOA.create_reference_with_id(id, tie._all_interfaces(tPOA,id)[0]) );
この動作は、IMPLICIT_ACTIVATION
ポリシーを使用して POA を作成した場合にだけ発生します。これはデフォルトの動作です。
サーバーで作成した参照は、クライアントに提供することができます。オブジェクト参照の作成とクライアントへのエクスポートの詳細については、「CORBA 2.3.1 仕様」のセクション 11.2.4 を参照してください。
アダプタアクティベータはオプションです。アダプタアクティベータは、要求の処理中に POA を作成する必要がある場合に使用します。アプリケーションの実行時に、必要な POA がすべて作成されている場合は、アダプタアクティベータは必要ありません。
アダプタアクティベータを使用すると、POA は、必要に応じて子 POA を作成できるようになります (子 POA (または複数の子のどれか) を指定した要求を受信したときの副作用として、あるいは起動パラメータ値 TRUE を使用して find_POA
メソッドが呼び出されたとき)。ORB は、存在していない子 POA への要求を受け取ると、アダプタアクティベータのオペレーションを呼び出します。アダプタアクティベータは必要な POA をその場で作成します。
要求は、ターゲットオブジェクトのオブジェクト ID と、ターゲットオブジェクト参照を作成した POA の識別情報を伝達できる必要があります。クライアントから要求が発行されると、ORB は、初めに適切なサーバーを探し (必要な場合は起動する)、次にそのサーバー内で適切な POA を探します。
サーバープロセス内に POA が存在しない場合、アプリケーションは、アダプタアクティベータを使用して必要な POA を再作成することができます。アダプタアクティベータは、ユーザーによって実装されるオブジェクトで、POA に関連付けることができます。アダプタアクティベータは、存在していない POA への要求を受け取った場合に、ORB によって呼び出されます。ここでアダプタアクティベータに、必要な POA を作成する機会が与えられます。そうしない場合、クライアントは ADAPTER_NONEXISTENT
例外を受け取ります。
ORB は、必要な POA を見つけると、その POA に要求を渡します。そのあとの要求の処理は、POA に関連付けられているポリシーと、オブジェクトの現在の起動状態によって異なります。
アダプタアクティベータの詳細については、CORBA 2.3.1 仕様のセクション 11.3.3 または AdapterActivatorOperations API ドキュメントを参照してください。
サーバントマネージャーはオプションです。サーバントマネージャーを使用すると、POA が、無効なオブジェクトに対する要求を受け取ったときに、必要なサーバントを起動できるようになります。サーバーが起動時にすべてのオブジェクトをロードする場合は、サーバントマネージャーは必要ありません。
サーバントマネージャーは、アプリケーション開発者が POA と関連付けることができるコールバックオブジェクトです。ORB はサーバントマネージャーのオペレーションを呼び出して、要求に応じてサーバントを活性化したり非活性化させたりします。サーバントマネージャーには、オブジェクト ID 値で特徴づけられるオブジェクト参照と特定のサーバントの関連を管理し、オブジェクト参照が存在するかどうかを決定する機能があります。各型のサーバントマネージャーは 2 つのオペレーションを実行できます。1 つはサーバントを見つけて返すためのオペレーションで、もう 1 つはサーバントを停止するためのオペレーションです。オペレーションは、その状況で使用できる情報の量によって異なります。
サーバントマネージャーを使用するには、USE_SERVANT_MANAGER
ポリシーを設定する必要があります。このポリシーを設定すると、POA 内のほかのポリシーに応じて、特定の状況で使用されるサーバントマネージャーの型が決まります。サーバントマネージャーには次の 2 つの型があります。
ServantActivator
RETAIN
ポリシーを持つ POA は、ServantActivators
であるサーバントマネージャーを使用します。
この型は、通常、持続オブジェクトを起動するために使われます。
ServantLocator
NON_RETAIN
ポリシーを持つ POA は、ServantLocators
であるサーバントマネージャーを使用します。POA は、このサーバントマネージャーによって返されるサーバントが単一の要求の処理にだけ使用されることを認識しているため、サーバントマネージャーのオペレーションに追加の情報を提供でき、サーバントマネージャーのオペレーションペアを連携させて ServantActivator
とは異なる処理を実行できます。POA が ServantLocator
インタフェースを使用する場合、preinvoke によって返されたサーバントの呼び出しオペレーションを実行した直後に、POA は、サーバントマネージャーの postinvoke を呼び出し、ObjectId 値および Servant 値をパラメータの一部として渡します。この機能は、POA に関連付けられたオブジェクトの各要求が強制的にサーバントマネージャーを介して行われるようにする場合に使用されます。
この型は、通常、一時オブジェクトを起動するために使われます。
サーバントマネージャーの詳細については、CORBA 2.3.1 仕様のセクション 11.3.4 を参照してください。
POA::createPOA に対する POAManager パラメータとして null を渡す場合は、新しく POA を作成するときに POAManager.activate() が必要です。null を渡すと、新しい POAManager が作成され、作成される POA に関連付けられます。この場合は、POAManager.activate() が必要です。
同じ POAManager を使用して複数の POA を制御するには、次の手順を実行します。
プログラマが上記のように明示的にプログラミングしないかぎり、ルート POA の POAManager とほかの POA の間に暗黙的な関係は存在しません。
詳細については、CORBA specification, formal/99-10-07 のセクション 11.3.2 を参照してください。