Tuxedo CORBA サーバ アプリケーションの開発方法

     前  次    新しいウィンドウで目次を開く     
ここから内容の開始

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

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

この章で説明される、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() オペレーションによって、口座番号がメッセージ バッファに格納され、このバッファが CURRBALANCE サービスの Oracle Tuxedo ATMI Teller アプリケーションに送信されます。
  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)
{
// 「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 サンプル アプリケーションの設計上の考慮事項

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 サンプル アプリケーションの構築、設定、および実行の詳細については、『Tuxedo CORBA University サンプル アプリケーション』を参照してください。


  ページの先頭       前  次