![]() ![]() ![]() ![]() ![]() ![]() ![]() |
この章では、Wrapperサンプル・アプリケーションを例にして、CORBAサーバー・アプリケーションによって管理されているオブジェクトの内部からOracle Tuxedoサービスを呼び出す方法の1つを概説します。
Wrapperサンプル・アプリケーションは、一連の課金用のオペレーションをOracle Tuxedo ATMI Tellerアプリケーションに委譲します。このアプリケーションは、基本的な課金の手続きを実行する一連のサービスを含んでいます。この章で紹介するアプローチは、Oracle TuxedoアプリケーションをOracle Tuxedoドメインに組み込むテクニックの一例です。
この章で示されている例では、CORBAオブジェクトのオペレーションと、アプリケーション内の特定のサービスへの呼出しとの1対1の対応が示されます。つまり、Oracle Tuxedoサービスへの呼出しがCORBAオブジェクトのオペレーションとしてラッピングされるとも言えます。これは、オブジェクトが処理機能をOracle Tuxedoアプリケーションに委譲することです。Oracle TuxedoサービスのセットをCORBAサーバー・アプリケーションで使用する必要があるときには、この章で説明されるテクニックを試みてください。
この章では、Oracle Tuxedo ATMIアプリケーションの詳細は説明しません。Oracle Tuxedo ATMIアプリケーションをビルドおよび構成する方法、および動作の詳細は、Oracle Tuxedoのオンライン・マニュアルに含まれているOracle Tuxedo ATMIの情報を参照してください。
この章で説明される、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()
オペレーションによって、口座番号がメッセージ・バッファに格納され、このバッファがOracle Tuxedo ATMI TellerアプリケーションのCURRBALANCE
サービスに送信されます。 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)
{
// "marshal" the "in" parameters (account number)
Fchg32(m_tuxbuf, ACCOUNT_NO, 0, (char*)&account, 0);
long size = Fsizeof32(tuxbuf);
// Call the CURRBALANCE Tuxedo service
if (tpcall("CURRBALANCE", (char*)tuxbuf, 0,
(char**)&tuxbuf, &size, 0) ) {
throw CORBA::PERSIST_STORE();
}
// "unmarshal" the "out" parameters (current balance)
CORBA::Double currbal;
Fget32(m_tuxbuf, CURR_BALANCE, 0, (char*)&currbal, 0);
return currbal;
}
次のサンプル・コードにある文は、メッセージ・バッファm_tuxbuf
を学生の口座番号で満たします。FMLの詳細は、『Oracle Tuxedo ATMI 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
オブジェクトを例にして示します)。
しかし、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サンプル・アプリケーションの構築、設定、および実行の詳細は、『CORBA Universityサンプル・アプリケーション・ガイド』を参照してください。
![]() ![]() ![]() |