CORBAサーバー・アプリケーションの作成

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

Oracle TuxedoサービスのCORBAオブジェクトへのラッピング

この章では、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サービスのラッピングの概要

この章で説明される、Oracle Tuxedoサービスのセットをラッピングする処理には以下のステップがあります。

  1. Oracle Tuxedoシステム向けの一連のタスクをオブジェクトの操作として構造化するオブジェクトを設計します。
  2. Oracle Tuxedoサービスによって使用されるメッセージ・バッファを作成します。このメッセージ・バッファは、Oracle Tuxedoサービスとの間でメッセージの送信および受信に使用されます。このバッファは、アプリケーションの実装ファイルでオブジェクトのコンストラクタに割り当てることができます。
  3. オブジェクト上に、Oracle Tuxedoサービスとの間でメッセージを送信および受信する操作を実装します。このステップには、Oracle Tuxedoサービスを呼び出す方法の実装を選択することも含まれます。

次の図は、クライアント・アプリケーション、CORBAサーバー・アプリケーションに管理されているCORBAオブジェクト、およびOracle Tuxedo ATMIアプリケーションの間の関係を簡単に示します。Oracle Tuxedo ATMIアプリケーションは、CORBAオブジェクトから呼び出されるサービスを実装します。

Oracle Tuxedoサービスをラッピングするオブジェクトの設計

この章で説明する第一のステップは、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オブジェクトの一般的な使用のシナリオは、以下のようになります。

  1. クライアント・アプリケーションによってRegistrarオブジェクトのregister_for_courses()操作が呼び出されて、このときに学生IDが要求されます。
  2. 登録の処理の一部として、RegistrarオブジェクトによってTellerオブジェクトのget_balance()操作が呼び出されて、口座番号が渡されます。
  3. Tellerオブジェクトのget_balance()操作によって、口座番号がメッセージ・バッファに格納され、このバッファがOracle Tuxedo ATMI TellerアプリケーションのCURRBALANCEサービスに送信されます。
  4. Oracle Tuxedo ATMI Tellerアプリケーションによって、メッセージ・バッファが受信され、その内容が取り出されてから、CURRBALANCEサービスに対して適切な呼出しが行われます。
  5. CURRBALANCEサービスによって、口座の現在の残高がUniversityデータベースから取得されて、Oracle Tuxedo ATMI Tellerアプリケーションに渡されます。
  6. Oracle Tuxedo ATMI Tellerアプリケーションによって、現在の残高がメッセージ・バッファに挿入され、Tellerオブジェクトに返されます。
  7. Tellerオブジェクトによって、現在の残高の合計がメッセージ・バッファから取り出された上で、現在の残高がRegistrarオブジェクトに返されます。

TellerオブジェクトおよびWrapperサンプル・アプリケーションの設計の詳細は、「Wrapperサンプル・アプリケーションの設計上の考慮事項」を参照してください。

Oracle Tuxedoサービス呼出しをカプセル化するバッファの作成

この章で説明される次のステップは、オブジェクトと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バッファを割り当てる行については、次のことに注意してください。

コード
説明
tpalloc
バッファを割り当てます。
"FML32"
FMLバッファ型を指定します。
""
一般に、Oracle Tuxedoサービスに渡されるフラグを記述する部分。この例では、渡されるフラグはありません。
1000
バッファ・サイズをバイト単位で指定します。

また、オブジェクトの実装ファイルは、Wrapperアプリケーションの実装ファイルにある次の文のようにして、デストラクタでバッファの割当てを解除する必要があります。

tpfree((char*)m_tuxbuf);

Oracle Tuxedoサービスとの間でメッセージを送信する操作の実装

次のステップは、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サンプル・アプリケーションの設計上の考慮事項

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 Universityサンプル・アプリケーションのしくみ

Wrapperサンプル・アプリケーションでの一般的な使用シナリオでは、以下のようなイベントのシーケンスを経ます。

  1. 学生のログオン手続きの後で、クライアント・アプリケーションによってRegistrarオブジェクトのget_student_details()操作が呼び出されます。get_student_details()操作の実装に含まれているコードによって、次の内容が取得されます。
    • データベースにある学生の表からの学生の口座番号
    • Tellerオブジェクト上でget_balance()操作を呼び出して取得される、データベースの口座表からの学生の残高
  2. 学生は、Basicサンプル・アプリケーションの場合と同様にコースを検索して、登録を希望するコースのリストを作成します。
  3. クライアント・アプリケーションは、Transactionサンプル・アプリケーションのシナリオと同様に、Registrarオブジェクトにリクエストを送信してregister_for_courses()操作を呼び出します。このリクエストにコース番号と学生IDのみが含められる点も同じです。
  4. 学生ごとにコースのリストを登録する際に、register_for_courses()操作は次の処理を呼び出します。
    • Tellerオブジェクトのget_balance()操作。学生の口座に滞納がないことを確認します。
    • Tellerオブジェクトのdebit()操作。Billingサーバー・アプリケーションによって管理され、コースの課金を行います。
  5. Tellerオブジェクトのget_balance()およびdebit()操作のそれぞれが、Oracle Tuxedo ATMI Tellerアプリケーションへのリクエストを送信します。このリクエストには、適切な呼出しが格納されたFMLバッファがカプセル化されています(これには、Oracle Tuxedo ATMI TellerアプリケーションのCURRBALANCEおよびDEBITサービスそれぞれへの口座番号呼出しも含まれます)。
  6. CURRBALANCEおよびDEBITサービスは、それぞれ、適切なデータベース呼出しを実行して、現在の残高を取得し、学生が登録したコースの課金を反映するように学生の口座から引き落とします。
  7. 学生の口座に滞納があれば、Registrarオブジェクトはクライアント・アプリケーションにDelinquentAccount例外を返します。その際、クライアント・アプリケーションはトランザクションをロールバックします。

    debit()操作が失敗した場合、TellerオブジェクトはTransactionCurrentオブジェクトのrollback_only()操作を呼び出します。TellerおよびRegistrarオブジェクトは同一のトランザクション内にスコープ指定されているため、このロールバックは、登録プロセスの全体に影響することで、データベースの不整合(たとえば、学生がコースに登録したのに、学生の口座残高からコースの分が引き落とされていないなど)を防ぎます。

  8. 例外が発生しなければ、Registrarオブジェクトによって学生は希望のコースに登録されます。

Billingサーバー・アプリケーションのインタフェース定義

以下のインタフェース定義が、Billingサーバー・アプリケーション用に定義されています。

Wrapperサンプル・アプリケーションの設計上の追加考慮事項

次の追加考慮事項が、Wrapperサンプル・アプリケーションの設計に影響します。

こうした考慮事項の両方により、Wrapperサンプル・アプリケーションのUBBCONFIGファイルが重要になります。以後の項では、これに関係する設計上の追加考慮事項を詳細に説明します。

Tellerオブジェクトへのリクエストの送信

ここまでは、Universityサーバー・アプリケーションのすべてのオブジェクトは同じサーバー・プロセス内で定義されていました。そのため、1つのオブジェクトが他のオブジェクトにリクエストを送信する処理は単純でした(この処理を、次のステップでRegistrarオブジェクトおよびCourseSynopsisEnumeratorオブジェクトを例にして示します)。

  1. Registrarオブジェクトが、CourseSynopsisEnumeratorオブジェクトへのオブジェクト参照を作成します。
  2. 新しく作成されたオブジェクト参照を使用して、RegistrarオブジェクトはCourseSynopsisEnumeratorオブジェクトへのリクエストを送信します。
  3. CourseSynopsisEnumeratorオブジェクトがメモリーに存在しない場合は、TPフレームワークがServerオブジェクトのServer::create_servant()操作を呼び出して、CourseSynopsisEnumeratorオブジェクトをインスタンス化します。

しかし、2つのサーバー・プロセスが実行中で、1つのプロセスにあるオブジェクトが2つめのプロセスによって管理されているオブジェクトにリクエストを送信する必要がある場合、その手順はやや複雑です。たとえば、別のサーバー・プロセスにあるオブジェクトへのオブジェクト参照を取得するには、重要な前提があります。1つは、2番目のサーバー・プロセスの実行中にリクエストを行うことです。さらに、別のサーバー・プロセスにあるオブジェクト用のファクトリが利用可能である必要があります。

Wrapperサンプル・アプリケーションでは、これを解決するために以下の構成および設計の要素を組み込んでいます。

例外の処理

Wrapperサンプル・アプリケーションは、学生による課金の総額が限度を超えた状況を処理できるように設計されています。学生がUniversityで許される限度を超えてコースを登録しようとした場合、Registrarオブジェクトはユーザー定義のDelinquentAccount例外を生成します。この例外がクライアント・アプリケーションに戻されると、クライアント・アプリケーションによってトランザクションがロールバックされます。ユーザー定義例外を実装する方法の詳細は、「ユーザー定義の例外」を参照してください。

Wrapperサンプル・アプリケーションのインタフェースに対するトランザクション・ポリシーの設定

Wrapperサンプル・アプリケーションのパフォーマンスに影響するもう1つの考慮事項は、アプリケーションのオブジェクトのインタフェースに適したトランザクション・ポリシーを設定することです。RegistrarCourseSynopsisEnumeratorおよびTellerオブジェクトは、alwaysトランザクション・ポリシーによって構成されます。RegistrarFactoryおよびTellerFactoryオブジェクトはignoreトランザクション・ポリシーによって構成されます(トランザクションに含まれる必要のないこれらのオブジェクトには、トランザクションのコンテキストが伝播されないようになります)。

UniversityおよびBillingサーバー・アプリケーションの構成

前述のように、Billingサーバー・アプリケーションは、UniversityデータベースおよびUniversityアプリケーション、Oracle Tuxedo ATMI Tellerアプリケーション、およびOracleトランザクション・マネージャ・サーバー(TMS)アプリケーションを含むグループとは別のグループで構成されます。

しかし、Billingサーバー・アプリケーションは学生をコースに登録するトランザクションに参加するので、Billingサーバー・アプリケーションはServerオブジェクトのTP::open_xa_rm()およびTP::close_xa_rm()操作への呼出しを含む必要があります。これは、任意のトランザクションに含まれるオブジェクトを管理するあらゆるサーバー・アプリケーションに対する要件です。そのようなオブジェクトがデータベースに対する読み取りまたは書込みの操作を一切実行しない場合は、次の場所にNULLリソース・マネージャを指定することができます。

Wrapperサンプル・アプリケーションの構築、設定、および実行の詳細は、『CORBA Universityサンプル・アプリケーション・ガイド』を参照してください。


  先頭に戻る       前  次