CORBAクライアント・アプリケーションの作成

     前  次    新規ウィンドウで目次を開く  新規ウィンドウで索引を開く  PDFとして表示 - 新規ウィンドウ  Adobe Readerを入手 - 新規ウィンドウ
コンテンツはここから始まります

動的起動インタフェースの使い方

このトピックには次の項が含まれます:

このトピックの情報はCORBA C++クライアント・アプリケーションに適用されます。

呼出し方式とDIIの概要については、「静的起動と動的起動」を参照してください。

このトピックで説明するCORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

注: Oracle Tuxedo CORBA JavaクライアントとOracle Tuxedo CORBA JavaクライアントORBはTuxedo 8.1で非推奨になり、サポートされなくなりました。Oracle Tuxedo CORBA JavaクライアントおよびOracle Tuxedo CORBA JavaクライアントORBのテキスト参照、関連するコード・サンプルはすべてサードパーティのJava ORBライブラリの実装/実行の簡易化とプログラマによる参照だけに使用する必要があります。
注: サード・パーティのCORBA Java ORBのテクニカル・サポートは、各ベンダーによって提供されます。Oracle Tuxedoでは、サード・パーティのCORBA Java ORBに関する技術的なサポートまたはドキュメントは提供していません。

 


DIIの使用

CORBAクライアント・アプリケーションからリクエストを送信する際、静的起動と動的起動を使い分けるのには、それ相応の理由があります。しかし、同じCORBAクライアント・アプリケーションで両方の呼出し方式を使用する必要がある場合もあります。呼出し方式を選択するには、DIIの利点と欠点を理解しておく必要があります。

静的起動と動的起動の大きな違いの1つは、どちらも同期一方向通信をサポートしているのに対し、動的起動だけが遅延同期通信をサポートしているという点です。

同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、レスポンスを取得するまで待機します。応答待ちの間、CORBAクライアント・アプリケーションはほかの作業を行うことができません。遅延同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、ほかの作業を自由に行うことができます。CORBAクライアント・アプリケーションは、要求が完了したかどうかを定期的にチェックし、完了した場合は、その要求の結果を利用します。

さらに、DIIを使用すると、CORBAクライアント・アプリケーションは、自身が記述された時点で未知であったCORBAオブジェクト型のメソッドを呼び出すことができます。これは、静的起動とは対照的です。静的起動では、CORBAクライアント・アプリケーションには呼び出すCORBAオブジェクトの各型に対するクライアント・スタブが含まれている必要があります。ただし、DIIでは、コードでクライアント・スタブの作業を実行する必要があるため、プログラミングが難しくなります。

CORBAクライアント・アプリケーションは、DIIを使用してより高いパフォーマンスを取得できます。たとえば、CORBAクライアント・アプリケーションは複数の遅延同期リクエストを同時に送信し、それらの完了を処理できます。リクエストが異なるサーバー・アプリケーションに送信された場合、この処理を並列に行うことができます。同期クライアント・スタブを使用している場合は、こうした処理を行うことができません。

注: クライアント・スタブは、最適化機能を備えています。このため、クライアント・スタブは、単一のリクエストを送信し、即座にブロックしてそのリクエストのレスポンスを取得するときに、DIIで達成されるレスポンス時間より短いレスポンスを達成できます。

DIIは、単なるCORBAクライアント・アプリケーションへのインタフェースです。CORBAサーバー・アプリケーションからは、静的起動と動的起動はまったく同じに見えます。

 


DIIの概念

多くの場合、DIIはあるタスクを達成するための複数の方法を提供します。それには、プログラミングの簡素化とパフォーマンスのトレード・オフが必要となります。この節では、DIIの使い方を理解するのに必要な高度な概念について説明します。このトピックの後半には、サンプル・コードなどの詳細を示します。

この項で説明する概念は次のとおりです。

リクエスト・オブジェクト

リクエスト・オブジェクトは、あるCORBAオブジェクトの1つのメソッドの1つの呼出しを表します。同じメソッドに対して2つの呼出しを行う場合、2つのリクエスト・オブジェクトを作成する必要があります。

メソッドを呼び出すには、そのメソッドが含まれているCORBAオブジェクトへのオブジェクト参照が必要です。オブジェクト参照を使用して、リクエスト・オブジェクトを作成し、そのリクエスト・オブジェクトに引数を指定し、リクエストを送信し、応答を待機して、リクエストの結果を取得します。

リクエスト・オブジェクトは、次の方法で作成できます。

CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

リクエスト送信オプション

リクエスト・オブジェクトを作成し、引数、結果の型、および例外の型を追加したら、そのリクエストをCORBAオブジェクトに送信します。リクエストは、以下の方法で送信できます。

注: CORBA::Request::send_deferredメンバー関数を使用する場合、ターゲット・オブジェクトが呼出しを発行するCORBAクライアント・アプリケーションと同じアドレス空間に存在するときには、リクエスト・オブジェクトの呼出しは同期的に動作します。この動作の結果、CosTransaction::Current::suspend操作を呼び出しても、CORBA::BAD_IN_ORDER例外は発生しません。トランザクションが完了したからです。

CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

リクエスト結果受信オプション

呼出しメソッドを使用してリクエストを送信した場合、結果を取得する方法は1つしかありません。その方法とは、リクエスト・オブジェクトのCORBA::Request::envメンバー関数を使用して例外をチェックし、例外が存在しない場合はCORBA::Request::resultメンバー関数を使用してリクエスト・オブジェクトからNVListを抽出することです。

遅延同期メソッドを使用してリクエストを送信した場合、次のいずれかのメンバー関数を使用して結果を取得できます。

CORBA::Request::send_onewayメンバー関数を使用する場合、結果は存在しません。

CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

 


DIIの開発プロセスのサマリー

クライアント・アプリケーションでのDIIの使用手順を表3-1に示します。

表3-1 DIIの開発プロセスのサマリー
手順
説明
1
CORBAインタフェースをインタフェース・リポジトリにロードします。
2
呼び出すメソッドが含まれるCORBAオブジェクトへのオブジェクト参照を取得します。
3
CORBAオブジェクト用のリクエスト・オブジェクトを作成します。
4
DIIリクエストを送信し、結果を取得します。
5
リクエストを削除します。
6
DIIでインタフェース・リポジトリを使用します。

以降の項では、これらのステップについて詳しく説明し、C++のサンプル・コードを示します。

 


ステップ1: CORBAインタフェースのインタフェース・リポジトリへのロード

DIIを使用するCORBAクライアント・アプリケーションを作成する前に、CORBAオブジェクトのインタフェースをインタフェース・リポジトリにロードしておく必要があります。CORBAオブジェクトのインタフェースがインタフェース・リポジトリにロードされていない場合、Oracle Application Builderにはそれらが表示されません。目的のCORBAインタフェースが「サービス」ウィンドウに表示されない場合は、idl2irコマンドを使用して、CORBAオブジェクトを定義するOMG IDLをインタフェース・リポジトリにロードします。idl2irコマンドの構文を表3-2に示します。

idl2ir [-f repositoryfile.idl] file.idl

表3-2 CORBAインタフェースのインタフェース・リポジトリへのロード
オプション
説明
-f repositoryfile
CORBAインタフェースのOMG IDLファイルを指定されたインタフェース・リポジトリにロードします。CORBAクライアント・アプリケーションがアクセスするOracle Tuxedoドメインのインタフェース・リポジトリの名前を指定します。
file.idl
CORBAインタフェースの定義が記述されているOMG IDLファイルを指定します。

idl2irコマンドの詳細は、『Oracle Tuxedoコマンド・リファレンス』を参照してください。

 


ステップ2: CORBAオブジェクトのオブジェクト参照の取得

Bootstrapオブジェクトを使用して、FactoryFinderオブジェクトを取得します。次に、FactoryFinderオブジェクトを使用して、DIIリクエストからアクセスするCORBAオブジェクトのファクトリを取得します。BoostrapオブジェクトとFactoryFinderオブジェクトを使用してファクトリを取得する例については、「ステップ4: CORBAクライアント・アプリケーションの記述」を参照してください。

 


ステップ3:リクエスト・オブジェクトの作成

CORBAクライアント・アプリケーションがCORBAオブジェクトのメソッドを呼び出す場合、そのメソッド呼出しのためのリクエストを作成します。このリクエストはバッファに書き込まれ、CORBAサーバー・アプリケーションに送信されます。CORBAクライアント・アプリケーションがクライアント・スタブを使用する場合、この処理は透過的に発生します。DIIを使用するクライアント・アプリケーションは、リクエスト・オブジェクトを作成し、そのリクエストを送信する必要があります。

CORBA::Object::_requestメンバー関数の使い方

次のC++のサンプル・コードに、CORBA::Object::_requestメンバー関数の使い方を示します。

Boolean          aResult;
CORBA::ULong long1 = 42;
CORBA::Any in_arg1;
CORBA::Any &in_arg1_ref = in_arg1;

in_arg1 <<= long1;
// Create the request using the short form
Request_ptr reqp = anObj->_request(“anOp”);
// Use the argument manipulation helper functions
reqp->add_in_arg() <<= in_arg1_ref;
// We want a boolean result
reqp->set_return_type(_tc_boolean);
// Provide some place for the result
CORBA::Any::from_boolean boolean_return_in(aResult);
reqp->return_value() <<= boolean_return_in;
// Do the invoke
reqp->invoke();
// No error, so get the return value
CORBA::Any::to_boolean boolean_return_out(aResult);
reqp->return_value() >>= boolean_return_out;

CORBA::Object::create_requestメンバー関数の使い方

CORBA::Object::create_requestメンバー関数を使用してリクエスト・オブジェクトを作成する場合、空のNVListを作成し、そのNVListに引数を1つずつ追加します。次に、リクエスト・オブジェクトを作成し、完成したNVListを引数としてそのリクエストに受け渡します。

リクエスト・オブジェクトの引数の設定

リクエスト・オブジェクトの引数は、名前付き/値オブジェクトを格納するNVListオブジェクトで表されます。このリスト内のオブジェクトの追加、削除、問合せを行うためのメソッドが用意されています。CORBA::NVListの詳細は、『CORBAプログラミング・リファレンス』を参照してください。

CORBA::NamedValueメンバー関数による入力引数と出力引数の設定

CORBA::NamedValueメンバー関数は、リクエストの入力引数と出力引数を表すために使用する名前付き/値オブジェクトを指定します。名前付き/値オブジェクトは、リクエスト・オブジェクトの引数として使用されます。また、CORBA::NamedValueのペアは、CORBAクライアント・アプリケーションに返されるリクエストの結果を表すためにも使用されます。名前付き/値オブジェクトの名前プロパティは文字列で、値プロパティはCORBA Anyによって表されます。

CORBA::NamedValueメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

CORBA::Object::create_requestメンバー関数の使用例

次のC++のサンプル・コードに、CORBA::Object::create_requestメンバー関数の使い方を示します。

CORBA::Request_ptr         reqp;
CORBA::Context_ptr ctx;
CORBA::NamedValue_ptr boolean_resultp = 0;
Boolean boolean_result;
CORBA::Any boolean_result_any(CORBA::_tc_boolean, & boolean_result);
CORBA::NVList_ptr arg_list = 0;
CORBA::Any arg;
// Get the default context
orbp->get_default_context(ctx);
// Create the named value pair for the result
(void) orbp->create_named_value(boolean_resultp);
CORBA::Any *tmpany = boolean_resultp->value();
*tmpany = boolean_result_any;

arg.replace(CORBA::_tc_long, &long_arg, CORBA_FALSE)
// Create the NVList
orbp->create_list(1, arg_list);

// Add an IN argument to the list
arg_list->add_value(“arg1”, arg, CORBA::ARG_IN);

// Create the request using the long form
anObj->_create_request (ctx,
“anOp”,
arg_list,
boolean_resultp,
reqp,
CORBA::VALIDATE_REQUEST );
// Do the invoke
reqp->invoke();

CORBA::NamedValue_ptr result_namedvalue;
Boolean aResult;
CORBA::Any *result_any;
// Get the result
result_namedvalue = reqp->result();
result_any = result_namedvalue->value();
// Extract the Boolean from the any
*result_any >>= aResult;

 


ステップ4: DIIリクエストの送信と結果の取得

リクエストは、使用する通信の方式に応じて複数の方法で呼び出すことができます。この項では、CORBAメンバー関数を使用してリクエストの送信と結果の取得を行う方法について説明します。

同期リクエスト

同期通信を行う場合、CORBA::Request::invokeメンバー関数はリクエストを送信し、そのレスポンスがCORBAクライアント・アプリケーションに返されるまで待機します。CORBA::Request::resultメンバー関数は、戻り値を表す名前付き/値オブジェクトの参照を返すために使用します。結果を取得したら、リクエストに格納されているNVListから値を読み出します。

遅延同期リクエスト

リクエストの送信用として、非ブロッキング・メンバー関数のCORBA::Request::send_deferredも用意されています。このメンバー関数を使用すると、CORBAクライアント・アプリケーションはリクエストを送信し、CORBA::Request::poll_response メンバー関数を使用してレスポンスが利用可能であるかどうかを調べることができます。CORBA::Request::get_responseメンバー関数は、レスポンスが利用可能になるまでブロックします。

次のサンプル・コードに、CORBA::Request::send_deferredCORBA::Request::poll_response、およびCORBA::Request::get_responseメンバー関数の使い方を示します。

request->send_deferred ();

if (poll)
{
for ( int k = 0 ; k < 10 ; k++ )
{
CORBA::Boolean done = request->poll_response();
if ( done )
break;
     }
}
request->get_response();

一方向リクエスト

一方向リクエストを送信するには、CORBA::Request::send_onewayメンバー関数を使用します。一方向リクエストでは、CORBAサーバー・アプリケーションからレスポンスが返されません。CORBA::Request::send_onewayメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。

次のサンプル・コードに、CORBA::Request::send_onewayメンバー関数の使い方を示します。

request->send_oneway();

複数のリクエスト

CORBA::Request::send_multiple_requests_deferredメンバー関数を使用してリクエスト・オブジェクトのシーケンスを送信する場合、CORBA::ORB::poll_responseCORBA::ORB::poll_next_response、CORBA::ORB::get_response、およびCORBA::ORB::get_next_responseメンバー関数を使用すると、CORBAサーバー・アプリケーションが各リクエストに対して送信するレスポンスを取得できます。

CORBA::ORB::poll_responseメンバー関数とCORBA::ORB::poll_next_responseメンバー関数を使用すると、CORBAサーバー・アプリケーションからレスポンスを取得したかどうかを調べることができます。これらのメンバー関数は、少なくとも1つのレスポンスが利用可能な場合は1を返し、利用可能なレスポンスが存在しない場合は0を返します。

CORBA::ORB::get_responseメンバー関数とCORBA::ORB::get_next_response メンバー関数を使用すると、レスポンスを取得できます。利用可能なレスポンスが存在しない場合、これらのメンバー関数はレスポンスを取得するまでブロックします。CORBAクライアント・アプリケーションがブロックしないようにする場合は、最初にCORBA::ORB::poll_next_responseメンバー関数を使用してレスポンスが利用可能かどうかを調べてから、CORBA::ORB::get_next_responseメソッドを使用してその結果を取得します。

また、CORBA::Request::send_multiple_requests_onewayメンバー関数を使用すると、複数の一方向リクエストを送信できます。

次のサンプル・コードに、CORBA::Request::send_multiple_requests_deferredCORBA::Request::poll_next_response、およびCORBA::Request::get_next_responseメンバー関数の使い方を示します。

CORBA::Context_ptr           ctx;
CORBA::Request_ptr requests[2];
CORBA::Request_ptr request;
CORBA::NVList_ptr arg_list1, arg_list2;
CORBA::ULong i, nreq;
CORBA::Long arg1 = 1;
Boolean aResult1 = CORBA_FALSE;
Boolean expected_aResult1 = CORBA_TRUE;
CORBA::Long arg2 = 3;
Boolean aResult2 = CORBA_FALSE;
Boolean expected_aResult2 = CORBA_TRUE

try
{
orbp->get_default_context(ctx);

populate_arg_list ( &arg_list1, &arg1, &aResult1 );

nreq = 0;

anObj->_create_request ( ctx,
“Multiply”,
arg_list1,
0,
requests[nreq++],
0);

populate_arg_list ( &arg_list2, &arg2, &aResult2 );

anObj->_create_request ( ctx,
“Multiply”,
arg_list2,
0,
requests[nreq++],
0 );

// Declare a request sequence variable...
CORBA::ORB::RequestSeq rseq ( nreq, nreq, requests, CORBA_FALSE );

orbp->send_multiple_requests_deferred ( rseq );
for ( i = 0 ; i < nreq ; i++ )
{
requests[i]->get_response();
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1;
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
aResult1 = CORBA_FALSE;
aResult2 = CORBA_FALSE;
// Using the same argument lists, multiply the numbers again.
// This time we intend to poll for response...

orbp->send_multiple_requests_deferred ( rseq );

// Now poll for response...
for ( i = 0 ; i < nreq ; i++ )
{
// We will randomly poll maximum 10 times...
for ( int j = 0 ; j < 10 ; j++ )
{
CORBA::Boolean done = requests[i]->poll_response();

if ( done ) break;
}
}
// Now actually get the response...
for ( i = 0 ; i < nreq ; i++ )
{
requests[i]->get_response();
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
aResult1 = CORBA_FALSE;
aResult2 = CORBA_FALSE;
// Using the same argument lists, multiply the numbers again.
// Call get_next_response, and WAIT for a response.
orbp->send_multiple_requests_deferred ( rseq );

// Poll until we get a response and then use get_next_response get it...
for ( i = 0 ; i < nreq ; i++ )
{
CORBA::Boolean res = 0;

while ( ! res )
{
res = orbp->poll_next_response();
}
orbp->get_next_response(request);
CORBA::release(request);
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1;
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
static void populate_arg_list (
CORBA::NVList_ptr ArgList,
CORBA::Long * Arg1,
CORBA::Long * Result )
{
CORBA::Any any_arg1;
CORBA::Any any_result;

(* ArgList) = 0;
orbp->create_list(3, *ArgList);

any_arg1 <<= *Arg1;
any_result.replace(CORBA::_tc_boolean, Result, CORBA_FALSE);
(*ArgList)->add_value(“arg1”, any_arg1, CORBA::ARG_IN);
(*ArgList)->add_value(“result”, any_result, CORBA::ARG_OUT);

return;
}

 


ステップ5: リクエストの削除

リクエストが正常に完了したことが通知されたら、既存のリクエストを削除するか、または次の呼出しでその一部を再利用するかを決定する必要があります。

リクエスト全体を削除するには、削除するリクエストに対してCORBA::Release(request) メンバー関数を使用します。この操作により、リクエストに関連するすべてのメモリーが解放されます。遅延同期通信を使用して発行されたリクエストを削除する場合、そのリクエストが完了していないときはそのリクエストが取り消されされます。

 


ステップ6: DIIでのインタフェース・リポジトリの使い方

CORBAクライアント・アプリケーションは、その作成時に未知であったオブジェクトのリクエストを作成、設定、および送信できます。そのために、CORBAクライアント・アプリケーションはインタフェース・リポジトリを使用して、リクエストを作成および設定するために必要な情報を取得します。CORBAクライアント・アプリケーションは、そのインタフェースのクライアント・スタブを持っていないので、DIIを使用してリクエストを送信します。

このテクニックは未知の型のCORBAオブジェクトの操作を呼び出すのに役立ちますが、インタフェース・リポジトリとの対話によるオーバーヘッドのため、パフォーマンスが問題となります。このタイプのDIIリクエストは、オブジェクトを参照するCORBAクライアント・アプリケーションを作成する場合か、または管理ツールのCORBAクライアント・アプリケーションを作成する場合に使用を検討します。

DIIリクエストでインタフェース・リポジトリを使用するための手順は次のとおりです。

  1. CORBA.hORB_INCLUDE_REPOSITORYを、Oracle Tuxedoシステム内でのインタフェース・リポジトリ・ファイルの格納場所に設定します。
  2. Bootstrapオブジェクトを使用して、インタフェース・リポジトリ・オブジェクトを取得します。このオブジェクトには、特定のOracle Tuxedoドメイン内のインタフェース・リポジトリの参照が含まれています。インタフェース・リポジトリの参照を取得したら、そのインタフェース・リポジトリをルートから参照できます。
  3. CORBA::Object::_get_interface メンバー関数を使用して、目的のCORBAオブジェクトを実装するCORBAサーバー・アプリケーションと通信します。
  4. CORBA::InterfaceDef_ptr を使用して、インタフェース・リポジトリに格納されているCORBAインタフェースの定義を取得します。
  5. FullInterfaceDescription操作で、目的の操作用のOperationDescriptionを検索します。
  6. OperationDescriptionからリポジトリIDを取得します。
  7. OperationDescriptionで返されたリポジトリIDを使用してCORBA::Repository::lookup_idを呼び出して、インタフェース・リポジトリ内のOperationDefを検索します。この呼出しにより、包含オブジェクトが返されます。
  8. 包含オブジェクトをOperationDefにナロー変換します。
  9. OperationDef引数とCORBA::ORB::create_operation_listメンバー関数を使用して、操作の引数リストを作成します。
  10. 操作リスト内の引数値を設定します。
  11. ほかのリクエストと同じように、リクエストを送信して結果を取得します。このトピックで説明した任意のオプションを使用して、リクエストを送信して結果を取得できます。

  先頭に戻る       前  次