![]() ![]() ![]() ![]() |
この章では、Wrapper サンプル アプリケーションを例にして、CORBA サーバ アプリケーションによって管理されているオブジェクトの内部から Oracle Tuxedo サービスを呼び出す方法の 1 つを概説します。
Wrapper サンプル アプリケーションは、一連の課金用のオペレーションを Oracle Tuxedo ATMI Teller アプリケーションに委譲します。このアプリケーションは、基本的な課金の手続きを実行する一連のサービスを含んでいます。この章で紹介するアプローチは、Oracle Tuxedo アプリケーションを Oracle Tuxedo ドメインに組み込むテクニックの一例です。
この章で示されている例では、CORBA オブジェクトのオペレーションと、アプリケーション内の特定のサービスへの呼び出しとの 1 対 1 の対応が示されます。つまり、Oracle Tuxdedo サービスへの呼び出しが CORBA オブジェクトのオペレーションとしてラッピングされるとも言えます。これは、オブジェクトが処理機能を Oracle Tuxedo アプリケーションに委譲することです。Oracle Tuxedo サービスのセットを CORBA サーバ アプリケーションで使用する必要があるときには、この章で説明されるテクニックを試みてください。
この章では、Oracle Tuxedo ATMI アプリケーションの詳細は説明しません。Oracle Tuxedo ATMI アプリケーションをビルドおよびコンフィグレーションする方法、および動作の詳細については、Oracle Tuxedo のオンライン マニュアルに含まれている Oracle Tuxedo ATIMI の情報を参照してください。
この章で説明される、Oracle Tuxedo サービスのセットをラッピングする処理には以下のステップがあります。
次の図は、クライアント アプリケーション、CORBA サーバ アプリケーションに管理されている CORBA オブジェクト、および Oracle Tuxedo ATMI アプリケーションの間の関係を簡単に示します。Oracle Tuxedo ATMI アプリケーションは、CORBA オブジェクトから呼び出されるサービスを実装します。
この章で説明する第一のステップは、Oracle Tuxedo ATMI アプリケーションへの呼び出しをラッピングするオブジェクトの設計です。たとえば、Wrapper サンプル アプリケーションの目的は、学生の登録プロセスに課金の機能を追加することで、これは既存の Oracle Tuxedo ATMI Teller アプリケーションに課金用オペレーションのセットを委譲すれば実現できます。
Wrapper サンプル アプリケーションで使用されている Oracle Tuxedo ATMI Teller アプリケーションには、次のサービスが含まれています。
これらのサービスをラッピングするために、Wrapper サンプル アプリケーションには新しいインタフェース Teller
を定義する別個の OMG IDL ファイルが含まれています。このインタフェースには、次のオペレーションがあります。
Teller
オブジェクトのこれらの各オペレーションは、Oracle Tuxedo ATMI Teller アプリケーションにあるサービスへの呼び出しと 1 対 1 でマップされています。
Teller
オブジェクトの一般的な使用のシナリオは、以下のようになります。
Registrar
オブジェクトの register_for_courses()
オペレーションが呼び出されて、このときに学生 ID が要求されます。Registrar
オブジェクトによって Teller
オブジェクトの get_balance()
オペレーションが呼び出されて、口座番号が渡されます。Teller
オブジェクトの get_balance()
オペレーションによって、口座番号がメッセージ バッファに格納され、このバッファが CURRBALANCE
サービスの Oracle Tuxedo ATMI Teller アプリケーションに送信されます。 CURRBALANCE
サービスに対して適切な呼び出しが行われます。CURRBALANCE
サービスによって、口座の現在の残高が University データベースから取得されて、Oracle Tuxedo ATMI Teller アプリケーションに渡されます。Teller
オブジェクトに返されます。Teller
オブジェクトによって、現在の残高の合計がメッセージ バッファから取り出された上で、現在の残高が Registrar
オブジェクトに返されます。
Teller
オブジェクトおよび Wrapper サンプル アプリケーションの設計の詳細については、「Wrapper サンプル アプリケーションの設計上の考慮事項」を参照してください。
この章で説明される次のステップは、オブジェクトと Oracle Tuxedo サービスの間でメッセージの送信に使用されるバッファの作成です。さまざまな Oracle Tuxedo ATMI アプリケーションで使用可能なバッファ型は複数あり、この章の例では FML バッファ型に基づいたバッファを使用します。Oracle Tuxedo システムのバッファ型の詳細については、Oracle Tuxedo の情報を参照してください。
使用するアプリケーション実装ファイルで、選択したバッファ型を割り当てる必要があります。割り当てるバッファは Teller
オブジェクトの特定のインスタンスについてユニークである必要がないので、オブジェクトのコンストラクタに割り当てることができます。この割り当てのオペレーションには、一般に、バッファ型の指定、Oracle Tuxedo サービスへのプロシージャ コールに適した任意のフラグの受け渡し、およびバッファ サイズの指定などが含まれます。
また、使用する実装のヘッダ ファイルには、バッファを表す変数の定義を追加する必要もあります。
次のサンプル コードでは Wrapper アプリケーションの Teller
オブジェクトのコンストラクタに、Oracle Tuxedo のバッファ m_tuxbuf
が割り当てられています。
Teller_i::Teller_i() :
m_tuxbuf((FBFR32*)tpalloc("FML32", "", 1000))
{
if (m_tuxbuf == 0) {
throw CORBA::INTERNAL();
}
}
FML バッファを割り当てる行については、次のことに注意してください。
また、オブジェクトの実装ファイルは、Wrapper アプリケーションの実装ファイルにある次の文のようにして、デストラクタでバッファの割り当てを解除する必要があります。
tpfree((char*)m_tuxbuf);
次のステップは、Oracle Tuxedo ATMI アプリケーションへの呼び出しをラッピングするオブジェクトでのオペレーションを実装することです。このステップでは、オブジェクトから Oracle Tuxedo サービスを呼び出す方法の実装を選択します。Wrapper サンプル アプリケーションでは、tpcall
実装が使用されます。
Oracle Tuxedo サービスをラッピングするオブジェクトでのオペレーションには、次のことをする文が一般に含まれます。
次の例は、Wrapper アプリケーションの Teller
オブジェクトでの get_balance()
オペレーションの実装を示します。このオペレーションでは特定の口座の残高が取得され、Oracle Tuxedo サービス CURRBALANCE
が呼び出されます。
CORBA::Double Teller_i::get_balance(BillingW::AccountNumber account)
{
// 「in」パラメータ (口座番号) をマーシャリングする
Fchg32(m_tuxbuf, ACCOUNT_NO, 0, (char*)&account, 0);
long size = Fsizeof32(tuxbuf);
// CURRBALANCE Tuxedo サービスを呼び出す
if (tpcall("CURRBALANCE", (char*)tuxbuf, 0,
(char**)&tuxbuf, &size, 0) ) {
throw CORBA::PERSIST_STORE();
}
// 「out」パラメータ (現在の残高) のマーシャリングを解除する
CORBA::Double currbal;
Fget32(m_tuxbuf, CURR_BALANCE, 0, (char*)&currbal, 0);
return currbal;
}
次のサンプル コードにある文は、メッセージ バッファ m_tuxbuf
を学生の口座番号で満たします。FML の詳細については、『Oracle Tuxedo FML リファレンス』を参照してください。
Fchg32(m_tuxbuf, ACCOUNT_NO, 0, (char*)&account, 0);
次の文は、tpcall
の実装を通じて CURRBALANCE
Oracle Tuxedo サービスを呼び出し、メッセージ バッファを渡します。また、この文は、Oracle Tuxedo サービスの応答が格納される場所も指定します。この例では、要求の送信元となったバッファと同じバッファです。
if (tpcall("CURRBALANCE", (char*)tuxbuf, 0,
(char**)&tuxbuf, &size, 0) ) {
throw CORBA::PERSIST_STORE();
}
次の文は、返された Oracle Tuxedo メッセージ バッファから残高を取り出します。
Fget32(m_tuxbuf, CURR_BALANCE, 0, (char*)&currbal, 0);
get_balance()
オペレーションの最後の行で、クライアント アプリケーションへ結果が返されます。
return currbal;
Oracle Tuxedo ドメイン内に Oracle Tuxedo サービスを組み込む方法については、次の制限事項に注意してください。
Wrapper サンプル アプリケーションの基本的な設計上の考慮事項は、この節で説明するシナリオに基づいています。学生がコースを登録するとき、Registrar
オブジェクトが登録プロセスの一部として Teller オブジェクトの呼び出しを実行し、Teller
オブジェクトは学生の口座にコースの課金をします。
ここでは、Wrapper サンプル アプリケーションの設計について説明し、Billing というサーバ アプリケーションをコンフィグレーションに追加します。このため、Wrapper サンプル アプリケーションには次の 4 つのサーバ アプリケーションがあります。
さらに、Wrapper サンプル アプリケーションの UBBCONFIG
ファイルで、次のグループが指定されます。
次の図に、Wrapper サンプル アプリケーションでの Oracle Tuxedo ドメインのコンフィグレーションを示します。
Oracle Tuxedo ATMI アプリケーションを University サンプル アプリケーションに組み込むことは、Process-Entity デザイン パターンを使用する観点からは合理的です。一般に Oracle Tuxedo ATMI アプリケーションは Process-Entity デザイン パターンを実装しますが、このデザイン パターンは University サンプル アプリケーションでも使用されています。
University データベースが更新されて、各学生の口座情報が格納されている新しいテーブルが含まれます。このため、Oracle Tuxedo ATMI Teller アプリケーションのサービスで課金データを処理する際には、University データベースを使用してトランザクションが実行されます。
Wrapper サンプル アプリケーションでの一般的な使用シナリオでは、以下のようなイベントのシーケンスを経ます。
Registrar
オブジェクトの get_student_details()
オペレーションが呼び出されます。get_student_details()
オペレーションの実装に含まれているコードによって、次の内容が取得されます。Registrar
オブジェクトに要求を送信して register_for_courses()
オペレーションを呼び出します。この要求にコース番号と学生 ID のみが含められる点も同じです。register_for_courses()
オペレーションは次の処理を呼び出します。Teller
オブジェクトの get_balance()
および debit()
オペレーションのそれぞれが、Oracle Tuxedo ATMI Teller アプリケーションへの要求を送信します。この要求には、適切な呼び出しが格納された FML バッファがカプセル化されています。これには、Oracle Tuxedo ATMI Teller アプリケーションの CURRBALANCE
および DEBIT
サービスそれぞれへの口座番号呼び出しも含まれます。CURRBALANCE
および DEBIT
サービスは、それぞれ、適切なデータベース呼び出しを実行して、現在の残高を取得し、学生が登録したコースの課金を反映するように学生の口座から引き落とします。
学生の口座に滞納があれば、Registrar
オブジェクトはクライアント アプリケーションに DelinquentAccount
例外を返します。その際、クライアント アプリケーションはトランザクションをロールバックします。
debit()
オペレーションが失敗した場合、Teller
オブジェクトは TransactionCurrent オブジェクトの rollback_only()
オペレーションを呼び出します。Teller
および Registrar
オブジェクトは同一のトランザクション内にスコープ指定されているため、このロールバックは、登録プロセスの全体に影響することで、データベースの不整合 (たとえば、学生がコースに登録したのに、学生の口座残高からコースの分が引き落とされていないなど) を防ぎます。
Registrar
オブジェクトによって学生は希望のコースに登録されます。
以下のインタフェース定義が、Billing サーバ アプリケーション用に定義されています。
次の追加考慮事項が、Wrapper サンプル アプリケーションの設計に影響します。
こうした考慮事項の両方により、Wrapper サンプル アプリケーションの UBBCONFIG
ファイルが重要になります。以後の節では、これに関係する設計上の追加考慮事項を詳細に説明します。
ここまでは、University サーバ アプリケーションのすべてのオブジェクトは同じサーバ プロセス内で定義されていました。そのため、1 つのオブジェクトがほかのオブジェクトに要求を送信する処理は明解でした。次のステップでは、Registrar
オブジェクトおよび CourseSynopsisEnumerator
オブジェクトを例にして示します。
Registrar
オブジェクトが、CourseSynopsisEnumerator
オブジェクトへのオブジェクト参照を作成します。 Registrar
オブジェクトは CourseSynopsisEnumerator
オブジェクトへの要求を送信します。CourseSynopsisEnumerator
オブジェクトがメモリに存在しない場合は、TP フレームワークが Server オブジェクトの Server::create_servant()
オペレーションを呼び出して、CourseSynopsisEnumerator
オブジェクトをインスタンス化します。
しかし、2 つのサーバ プロセスが実行中で、1 つのプロセスにあるオブジェクトが 2 つめのプロセスによって管理されているオブジェクトに要求を送信する必要がある場合、その手順はやや複雑です。たとえば、別のサーバ プロセスにあるオブジェクトへのオブジェクト参照を取得するには、重要な前提があります。1 つは、2 番目のサーバ プロセスの実行中に要求を行うことです。さらに、別のサーバ プロセスにあるオブジェクト用のファクトリが利用可能である必要があります。
Wrapper サンプル アプリケーションでは、これを解決するために以下のコンフィグレーションおよび設計の要素を組み込んでいます。
Server::initialize()
オペレーションにある TellerFactory
オブジェクトへのオブジェクト参照を取得する。次に、University サーバ アプリケーションは TellerFactory
へのオブジェクト参照をキャッシュします。これにより、Registrar
オブジェクトが TellerFactory
を必要とするたびに次の処理を実行せずに済むので、性能の最適化に貢献します。Registrar
オブジェクトによって TellerFactory
オブジェクトが呼び出されるとき、Registrar
オブジェクトは Server::initialize()
オペレーション (前項で説明したオペレーション) によって取得されたオブジェクト参照を使用します。UBBCONFIG
ファイルは、各サーバ プロセスの起動順に指定してください。Registrar
オブジェクトの register_for_courses()
および get_student_details()
オペレーションは、Teller
オブジェクトのオペレーションを呼び出すコードを含むように変更される。
Wrapper サンプル アプリケーションは、学生による課金の総額が限度を超えた場合を処理できるように設計されています。学生が University で許される限度を超えてコースを登録しようとした場合、Registrar
オブジェクトはユーザ定義の DelinquentAccount
例外を生成します。この例外がクライアント アプリケーションに返されると、クライアント アプリケーションによってトランザクションがロールバックされます。ユーザ定義例外を実装する方法の詳細については、「ユーザ定義の例外」を参照してください。
Wrapper サンプル アプリケーションの性能に影響するもう 1 つの考慮事項は、アプリケーションのオブジェクトのインタフェースに適したトランザクション ポリシーを設定することです。Registrar
、CourseSynopsisEnumerator
、および Teller
オブジェクトは、always
トランザクション ポリシーによってコンフィグレーションされます。RegistrarFactory
および TellerFactory
オブジェクトは ignore
トランザクション ポリシーによってコンフィグレーションされます。これらのオブジェクトには、トランザクションに含まれる必要がないので、トランザクションのコンテキストが伝達されないようになります。
前述のように、Billing サーバ アプリケーションは、University データベースおよび University アプリケーション、Oracle Tuxedo ATMI Teller アプリケーション、および Oracle トランザクション マネージャ サーバ (TMS) アプリケーションを含むグループとは別のグループでコンフィグレーションされます。
しかし、Billing サーバ アプリケーションは学生をコースに登録するトランザクションに参加するので、Billing サーバ アプリケーションは Server オブジェクトの TP::open_xa_rm()
および TP::close_xa_rm()
オペレーションへの呼び出しを含む必要があります。これは、任意のトランザクションに含まれるオブジェクトを管理するあらゆるサーバ アプリケーションに対する要件です。そのようなオブジェクトがデータベースに対する読み取りまたは書き込みのオペレーションを一切実行しない場合は、次の場所に NULL リソース マネージャを指定することができます。
Wrapper サンプル アプリケーションの構築、設定、および実行の詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。
![]() ![]() ![]() |