オブジェクト・アダプタは、オブジェクト参照を使用する要求と適切なコードを接続して、その要求にサービスを提供するメカニズムです。ポータブル・オブジェクト・アダプタ(POA)は、CORBA仕様によって定義された特別な種類のオブジェクト・アダプタです。POAは次の目標を満たすように設計されています。
このドキュメントでは、Java SEでの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の要求が順に処理されます。(注:このポリシーは、Java SEに含まれる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を参照してください。