![]() ![]() ![]() ![]() ![]() ![]() ![]() |
このトピックの情報は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に関する技術的なサポートやマニュアルは提供していません。 |
CORBAクライアント・アプリケーションからリクエストを送信する際、静的起動と動的起動を使い分けるのには、それ相応の理由があります。しかし、同じCORBAクライアント・アプリケーションで両方の呼出し方式を使用する必要がある場合もあります。呼出し方式を選択するには、DIIの利点と欠点を理解しておく必要があります。
静的起動と動的起動の大きな違いの1つは、どちらも同期oneway通信をサポートしているのに対し、動的起動だけが遅延同期通信をサポートしているという点です。
同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、レスポンスを取得するまで待機します。応答待ちの間、CORBAクライアント・アプリケーションはほかの作業を行うことができません。遅延同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、ほかの作業を自由に行うことができます。CORBAクライアント・アプリケーションは、要求が完了したかどうかを定期的にチェックし、完了した場合は、その要求の結果を利用します。
さらに、DIIを使用すると、CORBAクライアント・アプリケーションは、自身が記述された時点で未知であったCORBAオブジェクト型のメソッドを呼び出すことができます。これは、静的起動とは対照的です。静的起動では、CORBAクライアント・アプリケーションには呼び出すCORBAオブジェクトの各型に対するクライアント・スタブが含まれている必要があります。ただし、DIIでは、コードでクライアント・スタブの作業を実行する必要があるため、プログラミングが難しくなります。
CORBAクライアント・アプリケーションは、DIIを使用してより高いパフォーマンスを取得できます。たとえば、CORBAクライアント・アプリケーションは複数の遅延同期リクエストを同時に送信し、それらの完了を処理できます。リクエストが異なるサーバー・アプリケーションに送信された場合、この処理を並列に行うことができます。同期クライアント・スタブを使用している場合は、こうした処理を行うことができません。
注意: | クライアント・スタブは、最適化機能を備えています。このため、クライアント・スタブは、単一のリクエストを送信し、即座にブロックしてそのリクエストのレスポンスを取得するときに、DIIで達成されるレスポンス時間より短いレスポンスを達成できます。 |
DIIは、単なるCORBAクライアント・アプリケーションへのインタフェースです。CORBAサーバー・アプリケーションからは、静的起動と動的起動はまったく同じに見えます。
多くの場合、DIIはあるタスクを達成するための複数の方法を提供します。それには、プログラミングの簡素化と性能のトレード・オフが必要となります。この節では、DIIの使い方を理解するのに必要な高度な概念について説明します。このトピックの後半には、サンプル・コードなどの詳細を示します。
リクエスト・オブジェクトは、あるCORBAオブジェクトの1つのメソッドの1つの呼出しを表します。同じメソッドに対して2つの呼出しを行う場合、2つのリクエスト・オブジェクトを作成する必要があります。
メソッドを呼び出すには、そのメソッドが含まれているCORBAオブジェクトへのオブジェクト参照が必要です。オブジェクト参照を使用して、リクエスト・オブジェクトを作成し、そのリクエスト・オブジェクトに引数を指定し、リクエストを送信し、応答を待機して、リクエストの結果を取得します。
CORBA::Object::_request
メンバー関数を使用します。 CORBA::Object::_request
メンバー関数を使用して、そのリクエストで呼び出すインタフェース名だけを指定する空のリクエスト・オブジェクト(get_course_details
など)を作成します。リクエスト・オブジェクトを作成したら、CORBAサーバー・アプリケーションに送信する前に引数を指定する必要があります(存在する場合)。呼び出すメソッドで必要な引数ごとに、CORBA::NVList::add_value
メンバー関数を呼び出します。
また、CORBA::Request::result
メンバー関数を使用して、リクエストの結果の型を指定する必要があります。パフォーマンス上の理由から、Object Request Brokers (ORB)間で交換されるメッセージには型情報は含まれません。結果の型のプレース・ホルダーを指定することによって、応答から結果を適切に抽出するために必要な情報をORBに提供します。同様に、呼び出すメソッドによって例外が発生する可能性がある場合、リクエスト・オブジェクトを送信する前に例外用のプレース・ホルダーを追加する必要があります。
CORBA::Object::_create_request
メンバー関数を使用します。 CORBA::Object:: _create_request
メンバー関数を使用してリクエスト・オブジェクトを作成する場合、そのリクエストを行うために必要なすべての引数を受け渡し、その結果の型とそのリクエストが返す可能性のあるユーザー例外を指定します。このメンバー関数を使用することで、空のNVListを作成し、一度に1つの引数をNVListに追加し、リクエスト・オブジェクトを作成して、完成したNVListをそのリクエストに引数として受け渡します。CORBA::Object::_create_request
メンバー関数には、性能上のメリットがあります。複数のオブジェクトの同じオブジェクトを呼び出す場合、これらの引数を複数のCORBA::ORB::_create_request
呼出しで再利用できます。
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
リクエスト・オブジェクトを作成し、引数、結果の型、および例外の型を追加したら、そのリクエストをCORBAオブジェクトに送信します。リクエストは、以下の方法で送信できます。
CORBA::Request::invoke
メンバー関数を呼び出すことです。この関数は、応答メッセージを取得するまでブロックします。CORBA::Request::send_deferred
メンバー関数を使用することです。 CORBA::ORB::send_multiple_requests_deferred
メンバー関数を使用します。これは、リクエスト・オブジェクトのシーケンスを取ります。 CORBA::Request::send_oneway
メンバー関数を使用します。CORBA::ORB::send_multiple_requests_oneway
メンバー関数を使用します。 注意: | CORBA::Request::send_deferred メンバー関数を使用する場合、対象オブジェクトが呼出しを発行するCORBAクライアント・アプリケーションと同じアドレス空間に存在するときには、リクエスト・オブジェクトの呼出しは同期的に動作します。この動作の結果、CosTransaction::Current::suspend オペレーションを呼び出しても、CORBA::BAD_IN_ORDER 例外は発生しません。トランザクションが完了したからです。 |
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
呼出しメソッドを使用してリクエストを送信した場合、結果を取得する方法は1つしかありません。その方法とは、リクエスト・オブジェクトのCORBA::Request::env
メンバー関数を使用して例外をチェックし、例外が存在しない場合はCORBA::Request::result
メンバー関数を使用してリクエスト・オブジェクトからNVListを抽出することです。
遅延同期メソッドを使用してリクエストを送信した場合、次のいずれかのメンバー関数を使用して結果を取得できます。
CORBA::ORB::poll_response
このメンバー関数は、リクエストが完了し、処理の準備ができているかどうかを調べます。このメンバー関数はブロックしません。リクエストを処理できる場合、CORBAクライアント・アプリケーションはget_response()
またはget_next_response()
メンバー関数を使用してレスポンスを処理する必要があります。このメンバー関数は、レスポンスの処理順序を考慮しない場合、CORBAクライアント・アプリケーションが特定のレスポンスを待つ間にほかのリクエストを処理する場合、またはタイムアウトを設定する場合に使用します。
CORBA::ORB::poll_next_response
このメンバー関数は、未処理のリクエストが処理できる状態にあるかどうかを調べます。リクエストを処理できる場合、CORBAクライアント・アプリケーションはget_response()
またはget_next_response()
メンバー関数を使用してレスポンスを処理する必要があります。このメンバー関数は、リクエストの処理順序が重要ではなく、CORBAクライアント・アプリケーションが特定のレスポンスを待つ間にほかのリクエストを処理する場合に使用します。
CORBA::ORB::get_response
このメンバー関数は、特定のリクエストに対するレスポンスが完了して処理されるまでブロックします。このメンバー関数は、未処理のリクエストを特定の順序で処理する場合に使用します。
CORBA::ORB::get_next_response
このメンバー関数は、未処理のリクエストに対するレスポンスが完了して処理されるまでブロックします。このメンバー関数は、リクエストの処理順序が重要でない場合に使用します。
CORBA::Request::send_oneway
メンバー関数を使用する場合、結果は存在しません。
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
クライアント・アプリケーションでのDIIの使用手順を表3-1に示します。
以降の項では、これらのステップについて詳しく説明し、C++のサンプル・コードを示します。
DIIを使用するCORBAクライアント・アプリケーションを作成する前に、CORBAオブジェクトのインタフェースをインタフェース・リポジトリにロードしておく必要があります。CORBAオブジェクトのインタフェースがインタフェース・リポジトリにロードされていない場合、Oracle Application Builderにはそれらが表示されません。目的のCORBAインタフェースが「サービス」ウィンドウに表示されない場合は、idl2ir
コマンドを使用して、CORBAオブジェクトを定義するOMG IDLをインタフェース・リポジトリにロードします。idl2ir
コマンドの構文を表3-2に示します。
idl2ir [-f
repositoryfile.idl] file.idl
idl2ir
コマンドの詳細は、『Oracle Tuxedoコマンド・リファレンス』を参照してください。
Bootstrapオブジェクトを使用して、FactoryFinderオブジェクトを取得します。次に、FactoryFinderオブジェクトを使用して、DIIリクエストからアクセスするCORBAオブジェクトのファクトリを取得します。BoostrapオブジェクトとFactoryFinderオブジェクトを使用してファクトリを取得する例については、「ステップ4: CORBAクライアント・アプリケーションの記述」を参照してください。
CORBAクライアント・アプリケーションがCORBAオブジェクトのメソッドを呼び出す場合、そのメソッド呼出しのためのリクエストを作成します。このリクエストはバッファに書き込まれ、CORBAサーバー・アプリケーションに送信されます。CORBAクライアント・アプリケーションがクライアント・スタブを使用する場合、この処理は透過的に発生します。DIIを使用するクライアント・アプリケーションは、リクエスト・オブジェクトを作成し、そのリクエストを送信する必要があります。
次の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
メンバー関数を使用してリクエスト・オブジェクトを作成する場合、空のNVListを作成し、そのNVListに引数を1つずつ追加します。次に、リクエスト・オブジェクトを作成し、完成したNVListを引数としてそのリクエストに受け渡します。
リクエスト・オブジェクトの引数は、名前付き/値オブジェクトを格納するNVListオブジェクトで表されます。このリスト内のオブジェクトの追加、削除、問合せを行うためのメソッドが用意されています。CORBA::NVList
の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
CORBA::NamedValue
メンバー関数は、リクエストの入力引数と出力引数を表すために使用する名前付き/値オブジェクトを指定します。名前付き/値オブジェクトは、リクエスト・オブジェクトの引数として使用されます。また、CORBA::NamedValue
のペアは、CORBAクライアント・アプリケーションに返されるリクエストの結果を表すためにも使用されます。名前付き/値オブジェクトの名前プロパティは文字列で、値プロパティはCORBA Any
によって表されます。
CORBA::NamedValue
メンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
次の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;
リクエストは、使用する通信の方式に応じて複数の方法で呼び出すことができます。この項では、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_deferred
、CORBA::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();
onewayのリクエストを送信するには、CORBA::Request::send_oneway
メンバー関数を使用します。onewayのリクエストでは、CORBAサーバー・アプリケーションからレスポンスが返されません。CORBA::Request::send_oneway
メンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
次のサンプル・コードに、CORBA::Request::send_oneway
メンバー関数の使い方を示します。
request->send_oneway();
CORBA::Request::send_multiple_requests_deferred
メンバー関数を使用してリクエスト・オブジェクトのシーケンスを送信する場合、CORBA::ORB::poll_response
、CORBA::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
メンバー関数を使用すると、複数のonewayリクエストを送信できます。
次のサンプル・コードに、CORBA::Request::send_multiple_requests_deferred
、CORBA::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;
}
リクエストが正常に完了したことが通知されたら、既存のリクエストを削除するか、または次の呼出しでその一部を再利用するかを決定する必要があります。
リクエスト全体を削除するには、削除するリクエストに対してCORBA::Release(request)
メンバー関数を使用します。この操作により、リクエストに関連するすべてのメモリーが解放されます。遅延同期通信を使用して発行されたリクエストを削除する場合、そのリクエストが完了していないときはそのリクエストが取り消されされます。
CORBAクライアント・アプリケーションは、その作成時に未知であったオブジェクトのリクエストを作成、設定、および送信できます。そのために、CORBAクライアント・アプリケーションはインタフェース・リポジトリを使用して、リクエストを作成および設定するために必要な情報を取得します。CORBAクライアント・アプリケーションは、そのインタフェースのクライアント・スタブを持っていないので、DIIを使用してリクエストを送信します。
このテクニックは未知の型のCORBAオブジェクトのオペレーションを呼び出すのに役立ちますが、インタフェース・リポジトリとの対話によるオーバーヘッドのため、パフォーマンスが問題となります。このタイプのDIIリクエストは、オブジェクトを参照するCORBAクライアント・アプリケーションを作成する場合か、または管理ツールのCORBAクライアント・アプリケーションを作成する場合に使用を検討します。
DIIリクエストでインタフェース・リポジトリを使用するための手順は次のとおりです。
CORBA.h
のORB_INCLUDE_REPOSITORY
を、Oracle Tuxedoシステム内でのインタフェース・リポジトリ・ファイルの格納場所に設定します。CORBA::Object::_get_interface
メンバー関数を使用して、目的のCORBAオブジェクトを実装するCORBAサーバー・アプリケーションと通信します。 CORBA::InterfaceDef_ptr
を使用して、インタフェース・リポジトリに格納されているCORBAインタフェースの定義を取得します。 FullInterfaceDescription
オペレーションで、目的のオペレーション用のOperationDescription
を検索します。OperationDescription
からリポジトリIDを取得します。OperationDescription
で返されたリポジトリIDを使用してCORBA::Repository::lookup_id
を呼び出して、インタフェース・リポジトリ内のOperationDef
を検索します。この呼出しにより、包含オブジェクトが返されます。OperationDef
にナロー変換します。OperationDef
引数とCORBA::ORB::create_operation_list
メンバー関数を使用して、オペレーションの引数リストを作成します。
![]() ![]() ![]() |