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