この章では、トランザクションの主要な側面とアウトバウンド接続用のJ2CAトランザクション管理規約について説明します。この規約はトランザクション管理用の標準のJ2EEのプログラム・モデルを活用しており、1つの調整されたトランザクションのコンテキスト内の標準のインタフェースを通して、アプリケーションが複数の異種のEISにアクセスすることを可能にします。
ここでは次の内容について説明します。
OC4Jのトランザクションのサポートの詳細は、『Oracle Containers for J2EEサービス・ガイド』のJava Transaction APIの章を参照してください。
トランザクションのトピックは、データの整合性を保証するためにデータの更新およびデータの操作がいかに管理されるかを扱います。トランザクションにはただ1つのEISまたは複数のEISが関連する場合があります。特に後者の場合、トランザクションの最中に問題が発生したときにデータが一貫性のない状態に残されないことを保証し、更新を調整するために厳密なルールに従う必要があります。たとえばお金を1つの口座から別の口座へと移動するトランザクションの場合、一方の口座の残高だけが更新される状況は避ける必要があります。
次の各項では、トランザクションとその管理について簡単な概要を示し、再確認をします。
トランザクションは作業ユニットであり、一般的にはアプリケーション・コンポーネントと1つ以上のEISとの間でデータを更新したり操作したりする複数の操作で成り立っています。トランザクションは次の4つの基本的な特徴を持っている必要があります。すなわちすべてのトランザクション操作が完了したかロールバックされたかを保証する原子性、データの一貫性、1つのトランザクションが完了していない他のトランザクションの結果を参照することを防ぐ独立性、およびコミットされたトランザクションはコミット操作後のシステム障害においても永続することを保証する永続性です。通常、これらをまとめてACIDという頭文字で呼びます。
リソース・マネージャはトランザクションをサポートしないか、ローカル・トランザクションまたはグローバル・トランザクション(分散トランザクションまたはXAトランザクションとも呼ばれる)をサポートします。グローバル・トランザクションは、Java Transaction API(JTA)実装を通すなどの方法で外部トランザクション・マネージャによって管理されます。ローカル・トランザクションは一般に1つのリソース・マネージャの内部で管理されます。(オプションとして外部のトランザクション・マネージャで管理することもできますが、この結果、不必要なオーバーヘッドが発生する可能性があります。)1つのリソース・マネージャに対してトランザクションを実行し、ACIDプロパティを検証し、その後トランザクションをコミットすることは1フェーズのコミット・プロトコルと呼ばれます。完全なデータの一貫性および整合性を保証するために、複数のリソース・マネージャに対するトランザクションは、準備のフェーズとコミットのフェーズからなる2フェーズのコミット・プロトコルを使用する必要があります。すべてのリソース・マネージャが更新の準備ができるまで、更新はどのリソース・マネージャにもコミットされません。
1つのトランザクションにかかわるすべてのデータ操作はトランザクション・コンテキストを共有します。
Enterprise JavaBeansテクノロジは、データの整合性およびセキュリティのために設計されており、J2EEプラットフォームの全体のトランザクション・モデルにおいて大きな役割を果しています。J2EE Connector Architectureは、アプリケーション用のトランザクション管理を処理するように設計されたEJBアーキテクチャと密接に関連しています。1つ以上のEISとのトランザクションを実行するJ2EEアプリケーションは、通常EJBコンポーネントを通してそれを行います。
EJBテクノロジにおいて、トランザクション境界(原則的にはトランザクションの始めと終わり)はBeanによりBean管理のトランザクション境界と呼ばれるモデルにおいて管理されるか、コンテナによりコンテナ管理のトランザクション境界と呼ばれるモデルにおいて管理されるかのどちらかです。データ・アクセス用に設計されたエンティティBeanは、コンテナ管理のトランザクション境界を使用する必要があります。セッションBeanはどちらのモデルも使用できます。
J2CA接続に関連するトランザクションは、どちらの境界モデルが使用されていようとEJBトランザクションをシームレスに拡張することを目的としています。EJBメソッドがトランザクションの有効範囲内で実行する場合、EISがグローバル・トランザクションをサポートすると仮定すると、EJBにかわってEISによって行われるすべての作業はそのトランザクションの有効範囲内にあります。(グローバル・トランザクションをサポートしない1つのEISがどのようにグローバル・トランザクションに含まれるかの詳細は、「最終リソース・コミット最適化に対するOC4Jサポート」を参照してください。)
OC4JにおけるEJBの詳細は、『Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド』を参照してください。
Java Transaction API(JTA)はJ2EEプラットフォームのトランザクション管理の手段です。グローバル・トランザクションを実行するあらゆる標準的なJ2EEアプリケーションは、通常EJBを通して、またリソース・アダプタを使用してEISにアクセスしJTAを使用します。JTAの使用にはリソース・マネージャの外部のトランザクション・マネージャが関与しており、トランザクション全体を調整します。JTAはトランザクション・マネージャとトランザクションに関与するエンティティ、すなわち、アプリケーション・コンポーネント、アプリケーション・サーバーおよびリソース・マネージャとの間のインタフェースのセットです。
JTAが提供する重要な機能には先に紹介した2フェーズのコミットがあり、トランザクション中にリソース・マネージャの障害が発生した場合のトランザクション・リカバリを含みます。
OC4Jによって実装される主要なJTAインタフェースは、javax.transaction
パッケージのTransaction
、TransactionManager
およびUserTransaction
インタフェースを含みます。Transaction
オブジェクトはトランザクションを表しており、commit()
およびrollback()
といったメソッドを持っており、それによってアプリケーションはトランザクション内で操作を実行することができます。TransactionManager
オブジェクトは、OC4JのようなJ2EEコンテナがコンテナ管理のトランザクション境界用にトランザクションの境界を管理できるメソッドを持っています。UserTransaction
オブジェクトは、アプリケーションがBean管理のトランザクション境界用にトランザクションの境界を管理できるメソッドを持っています。アプリケーション・コンポーネントはJNDIを使用してUserTransaction
オブジェクトを検索します。詳細は、「トランザクション・マネージャによる実装: UserTransactionとTransactionManager」を参照してください。
JTAのjavax.transaction.xa.XAResource
インタフェースは、外部トランザクション・マネージャによって制御されるグローバル・トランザクションにおいて使用されるEISのようなリソースを表すためにリソース・アダプタ・プロバイダによって実装されます。トランザクション・マネージャはトランザクションに参加しているそれぞれのEIS接続用にXAResource
オブジェクトを取得し、それぞれのリソースをトランザクションに関連付けたり、トランザクションとの関連をなくしたりすることができます。詳細は、「リソース・アダプタによる実装: XAResourceとLocalTransaction」を参照してください。
Java Transaction APIの詳細は、『Oracle Containers for J2EEサービス・ガイド』を参照してください。
ローカル・トランザクションは1つのリソース・マネージャに特有なトランザクションであり、このリソース・マネージャに対して作成され、コミットされます。トランザクションはアプリケーション・コンポーネントまたはコンテナによって境界を定められます。
アプリケーション・コンポーネントによるデマーケーションは、たとえば(CCIを実装するリソース・アダプタ用に)CCIのLocalTransaction
インタフェースのメソッドや、(JDBCドライバ用に)commit()
およびrollback()
といったJDBCのjava.sql.Connection
インタフェースのメソッドなどのEIS固有のAPIを含みます。
コンテナによるデマーケーションはSPIのLocalTransaction
のインタフェースのメソッドを含みます。
注意: JTAトランザクションにおいて1つだけのリソース・マネージャが関与するコンテナ管理のトランザクション境界用には、コンテナは次の2つの選択肢を持っています。
|
前述のとおり、グローバル・トランザクションは一般に、JTAのXAResource
オブジェクトを使用します。このインタフェースは業界標準のX/Openトランザクション・モデルに基づいています。OC4Jのトランザクション・マネージャはトランザクションにかかわるすべてのリソース・マネージャを調整します。
データの整合性および一貫性のためにXAResource
オブジェクトは2フェーズ・コミット・プロトコルをサポートし、トランザクションがすべてのリソース・マネージャに対して正常にコミットされるか、またはどこにもコミットされないようにします。このプロトコルにおいてOC4Jのトランザクション・マネージャは、それぞれのリソース・マネージャのXAResource
のprepare()
メソッドをコールして保留中のコミットをリソース・マネージャに通知します。それぞれのリソース・マネージャに通知が届き、コミットに同意したときにだけ、トランザクション・マネージャはそれぞれのリソース・マネージャのXAResource
のcommit()
メソッドをコールしてトランザクションをコミットします。準備のフェーズにおいて通知が届かないかコミットに反対するリソース・マネージャがある場合は、トランザクション・マネージャはそれぞれのリソース・マネージャのXAResource
のrollback()
メソッドをコールしてトランザクションを中断します。
リソース・アダプタ・プロバイダによって提供されるra.xml
ファイルにおいて、リソース・アダプタのトランザクション・サポートのレベルは<transaction-support>
要素に示されています。J2EE Connector Architecture Specificationのバージョン1.5によると、これは<outbound-resourceadapter>
要素のサブ要素であり、次のグローバル・トランザクション・サポートの例に示すように、NoTransaction
、LocalTransaction
またはXATransaction
の値をサポートします。
<outbound-resourceadapter> ... <transaction-support>XATransaction</transaction-support> ... </outbound-resourceadapter>
(J2EE Connector Architecture Specificationのバージョン1.0では<transaction-support>
は<resourceadapter>
要素のサブ要素です。)
サポート・レベルは次のとおりです。
NoTransaction
: リソース・アダプタは、グローバル・トランザクション、ローカル・トランザクションを含め、トランザクションをまったくサポートしません。データは書き込まれ、更新されますが、EISとの複数の相互作用においてACIDプロパティは可能ではありません。
LocalTransaction
: リソース・アダプタはSPIのLocalTransaction
インタフェースを実装しておりローカル・トランザクションをサポートしますが、グローバル・トランザクションはサポートしません。
XATransaction
: リソース・アダプタはSPIのLocalTransaction
インタフェースおよびXAResource
インタフェースを実装しており、ローカル・トランザクションだけでなくグローバル・トランザクションもサポートします。
リソース・アダプタのトランザクションのサポート・レベルがXATransaction
であれば、接続をグローバル・トランザクションに登録するためにXAResource
オブジェクトが必要とされるとき、J2CAコンテナはManagedConnection
インスタンスのgetXAResource()
メソッドをコールします。リソース・アダプタのトランザクションのサポート・レベルがLocalTransaction
であれば、コンテナはLocalTransaction
オブジェクトを取得するためにgetLocalTransaction()
メソッドをコールします。ローカル・トランザクションレベルの接続がグローバル・トランザクションに登録される必要があれば、コンテナはエミュレートされたXAResource
を作成します。エミュレートされたXAResource
は登録され、それによってローカル・トランザクションレベルの接続はLocalTransaction
オブジェクトを通して(制限付きで)グローバル・トランザクションに参加することができます。
続く項においては、トランザクション管理において使用される主要なJ2CAおよびJava Transaction APIインタフェースを要約します。
リソース・アダプタ・プロバイダによって実装される次のそれぞれのインタフェースは、トランザクション管理規約において重要な役割を果しています。
javax.transaction.xa.XAResource
javax.resource.spi.LocalTransaction
XAResource
インスタンスまたはLocalTransaction
インスタンスは、SPIのManagedConnection
インタフェースに指定されるメソッドを通して管理接続から取得されます。アプリケーション・コンポーネントが接続をリクエストするとき、OC4Jは常にリソース・アダプタのManagedConnectionFactory
オブジェクトを通してリソース・アダプタからManagedConnection
オブジェクトを取得します。これは作業がトランザクションのコンテキストの中であるかどうかに関係ありません。ManagedConnection
オブジェクトは物理EIS接続を表しており、新しく作成されるか接続プールから取得されるかのどちらかです。(管理接続の取得の過程は、「接続管理規約の要約」に説明されています。)ManagedConnectionFactory
およびManagedConnection
を実装するクラスはリソース・アダプタ・プロバイダによって提供されます。
ManagedConnection
インタフェースは次のメソッドを指定します。
XAResource getXAResource()
LocalTransaction getLocalTransaction()
接続をリクエストするアプリケーション・コンポーネントがグローバル・トランザクションのコンテキストにあり、リソース・アダプタがXATransaction
のトランザクション・サポート・レベルであるならば、OC4Jは管理接続からXAResource
オブジェクトを取得するためにgetXAResource()
メソッドをコールします。その後OC4Jは、OC4Jのトランザクション・マネージャにXAResource
オブジェクトを登録します。(トランザクション・マネージャはグローバル・トランザクションに参加するそれぞれの接続用にXAResource
オブジェクトを取得します。)XAResource
オブジェクトによりEISは、OC4Jトランザクション・マネージャのような外部トランザクション・マネージャによって制御されるトランザクションに参加できます。トランザクション・マネージャは、関連付け、完了およびリカバリといったトランザクションの情報をEISと通信するためにXAResource
オブジェクトを使用します。
重要なXAResource
メソッドには、次のものがあります。
トランザクション・ブランチの作業を開始するためのvoid start(Xid, ...)
トランザクション・ブランチの作業を終了するためのvoid end(Xid, ...)
2フェーズのコミットの準備フェーズを実行するvoid prepare(Xid, ...)
2フェーズのコミットのコミット・フェーズを実行するvoid commit(Xid, ...)
トランザクションをロールバックするためのvoid rollback(Xid, ...)
これらはトランザクションを識別するためにjavax.transaction.xa.Xid
インスタンスを受け取ります。
接続をリクエストするアプリケーション・コンポーネントがローカル・トランザクションのコンテキストかグローバル・トランザクションのコンテキストにあるが、リソース・アダプタのトランザクションのサポート・レベルがLocalTransaction
のみであれば、OC4Jは管理接続からLocalTransaction
オブジェクトを取得するためにgetLocalTransaction()
メソッドをコールします。LocalTransaction
オブジェクトによってOC4JはEISとのローカル・トランザクションを管理することができます。
SPIのLocalTransaction
インタフェースは次の3つのメソッドを指定します。
ローカル・トランザクションを開始するためのvoid begin()
ローカル・トランザクションをコミットするためのvoid commit()
ローカル・トランザクションをロールバックするためのvoid rollback()
注意: リソース・アダプタ・プロバイダによって実装されるSPIのLocalTransaction インタフェースを、クライアント側での使用のためにオプションで実装されるCCIのLocalTransaction インタフェースと混同しないように注意してください。CCIインタフェースはアプリケーションレベルのローカル・トランザクション境界用です。SPIインタフェースはローカル・トランザクションの管理用にJ2EEコンテナによって使用されます。しかし両方のインタフェースは同じメソッドを定義します。 |
次のインタフェースはOC4Jトランザクション・マネージャといったトランザクション・マネージャによって実装されます。
javax.transaction.UserTransaction
javax.transaction.TransactionManager
OC4Jのトランザクション・マネージャによりグローバル・トランザクションは複数のEISに対してサポートされます。グローバル・トランザクションは、コンポーネント管理の(Bean管理の)シナリオにおいてアプリケーション・コンポーネント(一般にEJB)によって開始されるか、コンテナ管理の使用例においてOC4Jによって開始されるかのどちらかです。前のケースではコンポーネントは次のメソッドを含むUserTransaction
オブジェクトを使用します。
トランザクションを作成し、それを現在のスレッドと関連付けるためのvoid begin()
現在のスレッドと関連付けられたトランザクションをコミットするためのvoid commit()
現在のスレッドと関連付けられたトランザクションをロールバックするためのvoid rollback()
注意: グローバル・トランザクションのシナリオにおいて、アプリケーション・コンポーネントは(Bean管理のトランザクション境界に使用される)UserTransaction オブジェクトのbegin() メソッドをコールしましたが、OC4Jはリソース・マネージャ用の接続ハンドルがアプリケーションに返されるときはいつでもリソース・マネージャのXAResource オブジェクトをOC4Jのトランザクション・マネージャに登録します。OC4Jはアプリケーション・コンポーネントが接続をリリースまたは閉じるときにXAResource オブジェクトのトランザクション・マネージャへの関連をなくします。 |
コンテナ管理のシナリオにおいてグローバル・トランザクションがOC4Jによって開始されるとき、OC4Jは次のメソッドを含むTransactionManager
オブジェクトを通してトランザクションを管理します。
トランザクションを作成し、それを現在のスレッドと関連付けるためのvoid begin()
現在のスレッドと関連付けられたトランザクションをコミットするためのvoid commit()
現在のスレッドと関連付けられたトランザクションをロールバックするためのvoid rollback()
現在のスレッドに関連付けられていたトランザクション(Transaction
オブジェクト)を一時停止して戻し、またリソースのトランザクションへの関連をなくすためのTransaction suspend()
現在のスレッドとトランザクション(Transaction
オブジェクトによって表される)との関連付けを再開し、リソースとトランザクションを再度関連付けるためのvoid resume(Transaction)
一度トランザクションが始まりアプリケーション・コンポーネントが接続をリクエストすると、接続管理メカニズムは、「接続管理規約の要約」に説明されているように実行されます。
OC4JはSPIのConnectionEventListener
インタフェースを実装し、それによって接続とトランザクション・ステータスに関するEISからの通知を可能にし、それぞれのリスナー・インスタンスを適切な管理コネクション・ファクトリに登録します。
OC4Jは接続が閉じられたときの通知に依存して、接続のクリーンアップおよび接続のクローズに伴って必要となるあらゆるトランザクションのクリーンアップを行います。次のConnectionEventListener
メソッドはリソース・アダプタによってコールされます。
void connectionClosed(ConnectionEvent)
ローカル・トランザクションにおいて、OC4Jはトランザクションが開始、コミットおよびロールバックされるときの通知に依存します。次のConnectionEventListener
メソッドはリソース・アダプタによってコールされます。
void localTransactionStarted(ConnectionEvent)
void localTransactionCommitted(ConnectionEvent)
void localTransactionRolledback(ConnectionEvent)
これらのメソッドは、OC4Jが通知されているイベントを表すSPIのConnectionEvent
オブジェクトを受け取ります。
続く項ではJ2CAトランザクション管理のOC4J実装の重要な点を要約します。
次のリソース・アダプタ用のOC4Jの主要な機能は、J2EE Connector Architectureの要件を反映しています。
OC4Jは宣言済のリソース・アダプタによってサポートされるトランザクションのレベルを決定するためにra.xml
ファイルの<transaction-support>
要素を読みます。
OC4Jは、ローカル・トランザクションの進行中にグローバル・トランザクションが開始を試みるといった、アプリケーション・コンポーネント内のあらゆる無効なトランザクション境界の発生を検出し、回避します。
先に記載のとおり、OC4JはSPIのLocalTransaction
インタフェースに基づくローカル・トランザクション規約をサポートし、またXAResource
インタフェースの機能に基づくグローバル・トランザクションをサポートします。(「リソース・アダプタによる実装: XAResourceとLocalTransaction」を参照してください。)
OC4Jはリソース・マネージャへの1つの物理接続を使用するトランザクション用に1フェーズのコミット・プロトコルを使用できます。OC4Jによってサポートされている1フェーズのコミットの最適化は、トランザクションにおけるすべての論理接続が同じEISへの同じ物理接続を使用しているグローバル・トランザクション・コンテキストのシナリオのためのものであり、少なくとも1フェーズのコミット・プロトコルをサポートする必要があります。(たとえばすべての接続が同じデータ・ソースとユーザー名を使用すると仮定すると、接続の共有のために複数の論理接続がすべて同じ物理接続を指している場合があります。)この場合、OC4Jは2フェーズのコミット・プロトコルのコミット・フェーズだけを使用します。準備フェーズはスキップされます。
先に記載のとおり、OC4JはSPIのConnectionEventListener
インタフェースを実装しており、ローカル・トランザクションの開始、コミットおよびロールバックについてはリスナーからの通知に依存しています。グローバル・トランザクションについては、OC4Jは接続のクローズ・イベントの通知に依存しています。(「OC4Jによる実装: ConnectionEventListenerインタフェース」を参照してください。)
OC4Jは不完全なローカル・トランザクションを検出します。たとえば、ステートレス・セッションBeanがメソッドの起動を通してローカル・トランザクションを開始し、トランザクションを完了しないでメソッドから戻った場合、OC4Jはセッションを終了して例外をスローします。
アプリケーション・コンポーネントがメソッドの起動中の例外によって終了する場合、OC4Jは進行中のすべてのローカル・トランザクションをリセットし、あらゆるクライアント固有の状態をリセットします。
OC4Jは接続の共有をサポートします。「OC4Jにおける接続の共有について」を参照してください。
この項では、オプション機能またはJ2CA仕様の範囲外の機能のOC4Jのサポートについて説明します。ここでは次の内容について説明します。
一般に、アプリケーション・コンポーネントがトランザクションのコンテキストにおいて接続ハンドルをリクエストするとき、接続は自動的に、または積極的にトランザクションに登録されます。これは、接続が最終的に使用されずに不必要なオーバーヘッドを招く場合でも起こります。
遅延登録では、新しい接続は、それが実際にトランザクションで使用される場合にのみ、言い換えるとデータがその接続を通して送信される場合にのみトランザクションに登録されます。
リソース・アダプタとアプリケーション・サーバーの両方はこの機能を使用できるように遅延登録をサポートする必要があります。OC4Jの接続マネージャはSPIのLazyEnlistableConnectionManager
インタフェースの実装を通してこの機能をサポートしているので、管理接続用にLazyEnlistableManagedConnection
インタフェースを実装するどのようなリソース・アダプタにおいても遅延登録を使用することができます。管理接続は接続マネジャのlazyEnlist()
メソッドをコールし、それによって接続はそれが使用される場合にのみ登録されます。
リソース・アダプタとOC4Jの両方とも、他方が必要なインタフェースを実装するかどうかを決定できます。他方がサポートしていない場合はどちらも遅延登録を試みません。
Java Transaction APIとJ2EE Connector ArchitectureのOC4J 10.1.3の実装は、LocalTransaction
(1フェーズのコミット)をサポートする1つの(そしてただ1つの)リソース・アダプタが、XATransaction
(2フェーズのコミット)をサポートするリソース・アダプタとともにグローバル・トランザクションに含まれる状況のために最終リソース・コミット最適化をサポートしています。基本的に最終リソース・コミット最適化により、1つのXAに準拠しないリソースがルートのOC4JプロセスにおいてXAトランザクションに参加することが可能になります。1つ以上のXAに準拠しないリソースがトランザクションに登録される場合、登録の試行から例外がスローされます。
リソース・アダプタにとってこの最適化は、エミュレートされたXAリソースを通して通知を受け取るリソース・アダプタとともに、1フェーズのコミットのリソース・アダプタを表すEmulatedXAResource
タイプのインスタンスを使用してXAResource
オブジェクトをエミュレートすることによって行われます。1フェーズのコミット・プロトコルだけをサポートする第2のリソース・アダプタを含めるあらゆる試みに対して、OC4Jトランザクション・マネージャは例外をスローします。
1つのエミュレートされたXAリソースを含むグローバル・トランザクションのコミットのリクエストを受け取ると、トランザクション・マネージャは次の手順を取ります。
2フェーズのコミットのリソースのそれぞれのprepare()
コールを起動します。
2フェーズのコミットのリソースのすべての準備が成功した場合、エミュレートされたXAリソースのcommit()
(1フェーズ)がコールされます。
エミュレートされたXAリソースの1フェーズのコミットの完了が成功した場合、トランザクション・マネージャはグローバル・トランザクションのコミットの決定をログに残し、2フェーズのコミットのリソースのそれぞれのcommit()
をコールします。
あるいは、エミュレートされたXAリソースの1フェーズのコミットが失敗した場合、トランザクション・マネージャはグローバル・トランザクションのロールバックの決定をログに残し、2フェーズのコミットのリソースのそれぞれのrollback()をコールします。
詳細は、『Oracle Containers for J2EEサービス・ガイド』の「最終リソース・コミット」を参照してください。
最終リソース・コミット最適化に関する注意 最終リソース・コミット最適化に関して次のことに注意してください。
エミュレートされたXAリソースはSinglePhaseResource
インタフェースも実装しており、そのステータスをエミュレートされたリソースとしてOC4Jに通知します。
最終リソース・コミット最適化は、エミュレートされたXAリソースのcommit()
がコールされた後、トランザクション・マネージャがそのコールの結果を受け取る前に障害が発生した場合に問題となります。このような場合、グローバル・トランザクションの結果の原子性を保証することはできません。
エミュレートされたXAリソースでは、トランザクション・リカバリは適用可能ではありません。
トランザクション・マネージャにおいてロギングが無効になっている場合(この場合リカバリはできません)、トランザクション・マネージャはエミュレートされたXAリソースを標準のXAリソースとして扱います。
J2EE Connector Architectureに従って、OC4Jは通常、1つのトランザクションに複数のXAではないリソース・アダプタを含む試みをサポートしていません。(前述の項、「最終リソース・コミット最適化に対するOC4Jサポート」の説明は、1つのXAでないリソース・アダプタについてのみ記載しています。)
注意: ただし例外があります。トランザクション・マネージャにおいてロギングが無効になっている場合、リカバリは可能ではありませんが、複数の1フェーズのコミットのリソースがトランザクションに参加することができます。また、パフォーマンスのテストなどのテストのシナリオにおいては複数のエミュレートされたXAリソースがトランザクションにおいて使用される場合があります。 |
また、リソース・アダプタのサポート・レベルがXATransaction
であっても1フェーズのコミットだけをサポートする場合、(たとえ1フェーズのコミットのリソースがグローバル・トランザクションをエミュレートするXAResource
オブジェクトを提供することが可能であっても)グローバル・トランザクションを試みることはお薦めしません。2フェーズのコミットの真のサポートの欠如は、グローバル・トランザクションをコミットするときまでわかりません。
OC4JはSPIのConnectionEventListener
インタフェースの実装を通して無効なトランザクション境界のケースをフラグします。
たとえば、Bean管理の境界を使用するEJBがローカル・トランザクションを開始するとします(CCIのLocalTransaction
インタフェースがリソース・アダプタによってサポートされている場合はそれを使用するなどの方法によって)。さらにそのEJBが、ローカル・トランザクションを完了する前にUserTransaction
オブジェクトのbegin()
のコールを通してグローバル・トランザクションの開始を試みると仮定します。リソース・アダプタはOC4Jにローカル・トランザクションの開始のメッセージを送っていますが、OC4Jはグローバル・トランザクションが開始されようとした時点でローカル・トランザクションのコミットの通知またはローカル・トランザクションのロールバックの通知を受け取ってはいないので、UserTransaction
のbegin()
コールにおいて例外をスローします。
トランザクション管理規約用のOC4Jにおける構成はほとんど必要ありません。大部分の機能は背後に隠れています。しかし、トランザクション・リカバリは特別なユーザー名とパスワードの設定を必要とします。トランザクションの処理中に障害が発生した場合、OC4Jのリカバリ・マネージャはEISへの連絡を必要とする場合がありますが、EISは未確認のあらゆるトランザクションについて照会するために、通常は特別な資格証明を要求します。「トランザクション・リカバリの理解と構成」を参照してください。
Application Server Controlコンソールで、次のようにしてXAトランザクション・リカバリを構成できます。
適切なリソース・アダプタ用の「リソース・アダプタ」ホームページからアクセスした「コネクション・ファクトリ」タブで、構成するコネクション・ファクトリのJNDIロケーションを選択します。
「コネクション・ファクトリの編集」ページが表示されたら、「オプション」タブで次のタスクを実行します。
新しいユーザー名の追加。
ユーザー名の指定の後で、直接または間接的にパスワードを指定します。
直接パスワードの場合は、「パスワード」を選択してパスワードを入力します。
間接パスワードの場合は、「間接パスワード」を選択してキーを入力します(単にユーザー名の場合もあります)。OC4Jは「ユーザー・マネージャ」において検索を行うためにそのキーを使用します(特にjazn-data.xml
ファイルにおいて)。
既存のユーザー名またはパスワードの変更。
続く項では、OC4Jがトランザクションの前に、可能なトランザクション・レベルとリソース・アダプタのサポート・レベルについてどのように設定し、後にどのようにクリーンアップするかを説明します。
この項では、関与するすべてのリソース・アダプタのサポート・レベルがXATransaction
であるか、「最終リソース・コミット最適化に対するOC4Jサポート」で説明した最終リソース・コミット最適化が使用されているかのどちらかのグローバル・トランザクションのためのOC4Jのトランザクションの設定とクリーンアップを説明します。(NoTransaction
だけをサポートするリソース・アダプタのグローバル・トランザクションのシナリオでは、OC4Jは「接続管理規約の要約」の説明のように接続の設定を完了しますが、トランザクションの設定用にはいかなる手順も行いません。)
接続割当てリクエストがグローバル・トランザクションのコンテキストの中のJ2EEアプリケーション・コンポーネントから起動され、リソース・アダプタがXATransaction
サポート・レベルを提供する場合(または後述のように最終リソース・コミットのシナリオがある場合)、OC4Jは接続内で行われた作業をトランザクション・マネージャに登録するために次の手順を取ります。
新しく作成された管理接続か接続プールの既存の接続かのどちらかの管理接続をリソース・アダプタから取得します。詳細は、「接続管理規約の要約」を参照してください。
管理接続からXAResource
オブジェクトを取得します。OC4Jのトランザクション・マネージャはリソース・マネージャへトランザクションの通知をするときはいつでもXAResource
オブジェクトを使用します。
注意: 最終リソース・コミットのシナリオにおいてLocalTransaction だけをサポートするリソース・アダプタ用に、OC4Jは管理接続から直接XAResource オブジェクトを取得するかわりに、管理接続と関連付けられたEmulatedXAResource オブジェクトを取得するか、必要であれば作成します。この場合、次の手順においてXAResource をEmulatedXAResource に読み替えてください。 |
OC4Jのトランザクション・マネージャにXAResource
オブジェクトを登録します。
XAResource
オブジェクトのstart()
メソッドを起動します。接続を通して行われたあらゆる作業について、リソース・マネージャはその作業をトランザクション・ブランチに関連付けるように指示されます。
管理接続から接続ハンドルを作成し、それをアプリケーション・コンポーネントに返します。
アプリケーション・コンポーネントが接続ハンドルを閉じるとき、リソース・アダプタはOC4JにConnectionClosed
イベントを送ります。基礎となる管理接続用の未処理の接続ハンドルがない場合、OC4JはXAResource
オブジェクトのend()
メソッドをコールし、管理接続には(OC4Jのトランザクション・マネージャによって実行される)グローバル・トランザクションに関連付ける操作がこれ以上存在しないことをリソース・マネージャに知らせます。
この項では、関与するすべてのリソース・アダプタのサポート・レベルがLocalTransaction
かXATransaction
である場合の、ローカル・トランザクションのためのOC4Jのトランザクションの設定とクリーンアップを説明します。(NoTransaction
だけをサポートするリソース・アダプタのローカル・トランザクションのシナリオでは、OC4Jは接続の設定を「接続管理規約の要約」の説明のように完了しますが、トランザクションの設定またはクリーンアップ用にはいかなる手順も行いません。)
「グローバル・トランザクションの設定とクリーンアップ」の説明と同様に、ローカル・トランザクションはOC4Jによって開始されます。あるいは、J2EEアプリケーション・コンポーネントはアプリケーション・レベルのトランザクション境界インタフェースを使用して、ローカル・トランザクションを明示的に開始し、終了することができます。ローカル・トランザクションの開始に使用される特定のプロセスは、使用されている接続インタフェースによります。CCIをクライアント・インタフェースとして実装するリソース・アダプタ用に、アプリケーション・コンポーネントはCCIのLocalTransaction
オブジェクトをCCIのConnection
オブジェクトからgetLocalTransaction()
メソッドを通して取得することができます。
クライアントサイドのAPIの詳細にかかわらず、次の手順はローカル・トランザクションが開始されるときにリソース・アダプタとOC4Jとの間で実行されます。
リソース・アダプタはローカル・トランザクションを開始するようにというアプリケーション・コンポーネントからのリクエストを検出します。たとえばCCIにおいて、これはアプリケーション・コンポーネントがCCIのLocalTransaction
オブジェクトのbegin()
メソッドを起動するときです。
リソース・アダプタはOC4Jにローカル・トランザクションが開始することを通知します。OC4Jはこの通知によって適切なサービスを提供します。
リソース・アダプタはローカル・トランザクションを開始するためにEIS固有のプロセスを実行します。
同様に、アプリケーション・コンポーネントはリソース・アダプタによって提供されるAPIを使用してローカル・トランザクションを明示的に終了することができます。ローカル・トランザクションの開始の場合と同様に、ローカル・トランザクションの終了にどのメソッドを使用するかは使用されている接続インタフェースによります。
ローカル・トランザクションが終了されるときにリソース・アダプタとOC4Jの間で起こることを次に示します。
リソース・アダプタはアプリケーション・コンポーネントからローカル・トランザクションを終了するようにというリクエストを検出します。たとえばCCIにおいてこれは、アプリケーション・コンポーネントがCCIのLocalTransaction
オブジェクトのcommit()
またはrollback()
メソッドを起動するときです。
リソース・アダプタはOC4Jにローカル・トランザクションが終了したことを通知します。OC4Jはその後、内部の状態を適宜更新します。
リソース・アダプタはEISのローカル・トランザクションをコミットまたはロールバックするためにEIS固有のプロセスを実行します。
J2EE Connector Architectureに定められている接続の共有は、複数の接続ハンドルが1つのトランザクションの中の複数のアプリケーション・コンポーネント間で共有されることを可能にします。これによって、よりよいパフォーマンスおよびリソースのより効率的な使用が可能になり、またリソース・マネージャのロックの競合と読取り分離の問題を回避することができます。続く項ではこの機能について説明します。
この項ではOC4Jにおける接続の共有の条件について説明します。
J2EEアプリケーション・コンポーネントによって新しい接続がリクエストされるとき、次の条件が満たされる場合、OC4Jは接続プール内の既存の物理接続から新しい接続ハンドルを返そうとします。
接続リクエストは、既存の物理接続を通してアクセスされたものと同じリソース・マネージャ用であり、また同じデータ・ソースを使用します。
接続リクエストは、セキュリティ属性、分離レベル、文字設定およびローカライゼーションなどの物理接続のプロパティと同じプロパティを持っています。
接続をリクエストするアプリケーション・コンポーネントは、現在物理接続を使用しているアプリケーション・コンポーネントと同じトランザクションの有効範囲内にあります。
アプリケーション・コンポーネントは共有可の有効範囲を持っており、リソース・マネージャから取得された物理接続は複数の論理接続の間で共有されます。これはデフォルトになっていますが、標準のejb-jar.xml
またはweb.xml
構成ファイル内の適用可能な<resource-ref>
要素の下に明示的に指定することができます。次の例において、EISへの論理接続ハンドルを作成するためにアプリケーション・コンポーネントは<res-ref-name>
要素に指定されているJNDIロケーションであるeis/myEIS
からコネクション・ファクトリを検索できます。<res-sharing-scope>
要素の値がshareable
と宣言されているので、接続の共有の他の条件が満たされていれば、アプリケーション・コンポーネントの複数の接続ハンドルは1つの物理接続を共有することができます。
<resource-ref> <res-ref-name>eis/myEIS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Application</res-auth> <res-sharing-scope>shareable</res-sharing-scope> </resource-ref>
unshareable
の設定によって共有を無効化することができます。1つ以上のコンポーネントがあるリソースからの接続を共有可と宣言し、一方、1つ以上の他のコンポーネントが同じリソースからの接続を共有不可と宣言することは可能です。
注意:
|
接続の共有は、トランザクションのサポート・レベルがNoTransaction
のリソース・アダプタ用にはサポートされていません。
この項では、接続の共有のサンプルのシナリオについて説明します。EJB1とEJB2という2つのEJBセッションBeanを持つアプリケーションがあると仮定します。両方ともローカル・トランザクションが可能な同じリソース・アダプタを使用して、1つのローカル・トランザクション内の同じEISに接続します。EISはデフォルトまたは設定により共有可です。ローカル・トランザクションは常に1つの物理接続に関連付けられているので、このシナリオのEJB1およびEJB2はローカル・トランザクションの有効範囲において同じ物理接続を共有しています。
次の操作を考えてみます。
クライアント・アプリケーションはトランザクションのコンテキストを持たないEJB1のメソッドをコールします。EJB1におけるメソッドの実装はコンテナ管理のトランザクション境界を使用し、EISへの接続をリクエストします。
接続が取得されるとその時点でOC4Jはローカル・トランザクションを開始します。このトランザクションは接続ハンドルが取得された管理接続オブジェクトに関連付けられていますが、ここで管理接続オブジェクトは物理接続を表しています。EJB1により接続を通してEISに実行された作業はローカル・トランザクションのコンテキストの中に含まれます。
EJB1はEJB2のメソッドをコールし、EJB2のメソッドの実装はEISへの接続をリクエストします。
OC4JはEJB1によってリクエストされた接続用と同じ管理接続オブジェクトを使用してEJB2に接続ハンドルを返します。OC4Jはまた、EJB1からEJB2へのメソッドのコールに対して、この管理接続オブジェクトとローカル・トランザクションのコンテキストとの関連付けを保持します。EJB2が接続を通してEISに実行する作業はローカル・トランザクションのコンテキストの中に含まれます。そのためこのシナリオにおいて、オープン・カーソルなどの接続の状態はEJB1とEJB2の間のメソッドのコールに対して保持されます。
EJB1からコールされた接続ハンドルのメソッドが完了する前に、EJB2がその接続ハンドルのclose()
メソッドをコールする場合、OC4Jはこの時点ではいかなる物理接続のクリーンアップも開始しません。これはその物理接続に関連付けられた不完全なローカル・トランザクションがまだ存在するからです。
EJB1が制御を取り戻したとき、EJB1はclose()
メソッドを呼ばなかったと仮定してその接続ハンドルをまだ使用することができます。
ここでEJB1がその接続ハンドルのclose()
メソッドを最終的にコールすると仮定します。物理接続に関連付けられた不完全なローカル・トランザクションがまだ存在するため、OC4Jはこの時点では物理接続のいかなるクリーンアップも開始しません。OC4Jはまだローカル・トランザクションのプロセスを完了する必要があります。
クライアント・アプリケーションからの元のメソッドのコールが完了すると、OC4Jはローカル・トランザクションをコミットします。
管理接続オブジェクトはそのローカル・トランザクション状態のクリーンアップを行います。
OC4Jはプールに物理接続を返します。
この項では、アウトバウンド接続を通してアクセスされるリソース・マネージャ用の2フェーズのコミットのリカバリ用のOC4Jのサポートを説明します。
トランザクション・リカバリの目的は、複数のEISに対する(グローバル)トランザクションの間に1つのEISが機能しなくなったときのデータ操作におけるデータの整合性を保持することにあります。そのため、トランザクション・リカバリはローカル・トランザクションや1フェーズのコミット・トランザクションには適用可能ではありません。
ここでは次の内容について説明します。
OC4Jがトランザクションの間に突然停止したり、リソース・マネージャへの接続を失ったりしたとき、OC4Jは(トランザクション状態によって)リカバリ・モードに入り、障害の時点に処理中であったトランザクションを完了するための手順を試みます。リカバリの責任はOC4Jのリカバリ・マネージャに委任されています。アプリケーション自身が関与することはありません。
XAリカバリにおける最初の手順はトランザクションの状態を決定することであり、その後、トランザクションの状態がリカバリを必須とするならば、必要なXAResource
オブジェクトの取得が試みられます。リカバリが必要であれば、OC4JはEISへの接続をすぐに再確立しようとします。次の状況においては、適用可能なコネクション・ファクトリ用のユーザー名とパスワードのサインオン情報が必要とされます。
アプリケーションがコンポーネント管理のサインオンを使用しており、アプリケーションはOC4Jには不可視のサインオン情報を提供する。
EISは、J2EEアプリケーションが使用するアカウントとは異なる特別な権限を持つユーザー・アカウントを通してのみトランザクション・リカバリが行われることを要求する。
アプリケーションがコンテナ管理のサインオンを使用しており、EISがリカバリ用に特別なサインオンを要求しない場合、OC4Jはリカバリのサインオン情報を要求しません。
表4-1はOC4JのXAリカバリのシナリオを要約しています。
表4-1 OC4JのXAリカバリのシナリオ
元の接続用のサインオン・モード | サインオン資格証明用のモード | XAリカバリの資格証明 |
---|---|---|
コンポーネント管理(アプリケーションが接続の資格証明を提供) |
OC4JはEISへのサインオン用のユーザー名とパスワードを意識しておらず、また保存していません。 |
XAリカバリの資格証明はユーザーの構成によります。(次の項、「OC4JにおけるXAリカバリの構成」を参照してください。)XAリカバリのサインオン構成を提供していない場合、OC4Jはユーザー名とパスワードなしにEISへの接続を試みます。これが失敗した場合、トランザクション・リカバリは失敗します。 |
コンテナ管理 |
OC4JはEISへの接続用のユーザー名とパスワードを決定します。アプリケーションにサインオンしたユーザー(OC4Jユーザー)に基づいてOC4Jはセキュリティ・マッピングを適用し、それによってユーザーはEIS用のユーザー名とパスワードを取得できます。 |
XAリカバリの資格証明はユーザーの構成によります。XAリカバリのサインオン情報を提供しない場合、OC4JはOC4Jユーザー情報を取得してセキュリティ・マッピング・メカニズムを使用し、EIS用のユーザー名とパスワードを決定し、EISに接続します。 |
接続が再確立されると接続からXAResource
オブジェクトが取得され、リカバリを完了するために使用されます。
注意: 次のことにも注意してください。
|
コネクション・ファクトリ用のXAリカバリのサインオン・パラメータを構成するために、Application Server Controlコンソールにおいて次の手順を取ります。
適切なリソース・アダプタ用の「リソース・アダプタ」ホームページからアクセスした「コネクション・ファクトリ」タブで、構成するコネクション・ファクトリのJNDIロケーションを選択します。
「コネクション・ファクトリの編集」ページが表示されたら「オプション」タブにおいて次のことができます。
新しいユーザー名の追加。ユーザー名の指定の後で、直接または間接的にパスワードを指定できます。直接パスワード用には「パスワード」を選択してパスワードを入力します。間接パスワード用には「間接パスワード」を選択してキーを入力します(たとえばそれは単にユーザー名の場合もあります)。OC4Jは「ユーザー・マネージャ」において検索を行うためにそのキーを使用します(特にjazn-data.xml
ファイルにおいて)。
既存のユーザー名またはパスワードの変更。
表4-2では、サインオンのプロパティについて説明し、oc4j-ra.xml
ファイルの対応するXML要素を示します。これらは<connector-factory>
のサブ要素である<xa-recovery-config>
のサブ要素の<password-credential>
のサブ要素です。
Application Server Controlオンライン・ヘルプのコネクション・ファクトリ・オプションの編集ページに関する状況依存トピックも参照してください。
OC4Jは接続の遅延登録の1つの型であるJ2CAの接続ラッピングを提供しており、接続がトランザクションに適切に登録されることを保証しています。接続ラッピングは接続の関連付けをサポートします。
J2EE Connector Architectureは、アプリケーションレベルの接続ハンドルとManagedConnection
(物理接続)インスタンスとの関連付けを規定しています。それぞれの接続リクエスト用に、ManagedConnection
インスタンスから接続ハンドルが作成されます。接続ハンドルは基礎となるManagedConnection
インスタンスとの関連付けを保持します。
J2EEコンポーネントがトランザクションの境界を越えて接続ハンドルをキャッシュするとき、コンテナはトランザクションの正確さを保持するために、ハンドルを異なる物理接続に再度関連付ける必要がある場合があります。この再度の関連付けなしでは、1つのトランザクション内で行われた作業と、異なるトランザクション内で行われた作業が混乱する可能性があります。
コンテナは接続の関連付けを使用して、接続ハンドルが、現在のトランザクションのコンテキストと接続の共有の有効範囲にとって適切である物理接続との関連付けを維持することを保証します。ManagedConnection
インタフェースのassociateConnection
メソッドを通して、コンテナは接続ハンドルと管理接続インスタンスとの関連付けを変更できます。associateConnection
メソッドは、与えられた接続ハンドルをそれが関連付けられているManagedConnection
インスタンスから切り離し、接続ハンドルをそれ自身と再度関連付けます。
接続ハンドルは1つのManagedConnection
インスタンスから別のインスタンスへとスイッチされることができます。接続ハンドルのメソッドが起動されるとき、正しいトランザクションの有効範囲にある適切な共有のManagedConnection
インスタンスを指すようにコンテナはハンドルを透過的にスイッチする必要がある場合があります。J2EE Connector仕様は、コンテナがどのようにトランザクションの境界を越えられたと判断するかについて規定していません(新しいトランザクションのコンテキストにおいて、作業がキャッシュされた接続において行われているとき)。
注意: ほとんどの場合、トランザクションの境界を越えて使用される接続ハンドル用のManagedConnection インスタンスのスイッチは、接続が共有可の場合にのみ要求されます。アプリケーションはそれが参照する接続が共有不可であると指摘できます。共有不可とマークされた接続は1つの接続ハンドルによってのみ参照されることができます。これは共有不可の接続用の接続ハンドルが開いているかぎり、それは同じManagedConnectionとの関連付けを維持できることを意味します。接続ハンドルがトランザクションの境界を越えてキャッシュされる場合でもこのことは言えます。 |
J2CAの遅延接続関連付け最適化により、J2CAコンテナは休眠中のManagedConnection
インスタンスを再生することができ、それによって接続リソースのより最適な使用が可能になります。これは、J2CAコンテナに対して接続ハンドルをそれが関連付けられたManagedConnection
インスタンスから切り離すことを許可し、ハンドルを無効の状態のままにし、ManagedConnection
インスタンスを再利用のために開放することによって行われます。次に接続ハンドルが使用されるとき、それは適切なManagedConnection
インスタンスと再度関連付けられる必要があります。ハンドルがManagedConnection
インスタンスから切り離された場合に接続ハンドルが再度関連付けられる必要があるときのJ2CAコンテナへの通知は、遅延関連付けではリソース・アダプタにより決まります。
注意: 遅延接続関連付けはリソース・アダプタにとってオプションです。 |
ほとんどの場合、接続の関連付けのメカニズムは、接続ハンドルが現在のトランザクションのコンテキストに適切なManagedConnection
インスタンスと関連付けられることを保証します。しかし、接続ハンドルがトランザクションの境界を越えて使用される場合は、共有不可の接続の場合と同様に、接続の再度の関連付けは適切ではありません。これらの場合、J2CAコンテナは現在関連付けられているManagedConnection
インスタンスが現在のトランザクションのコンテキストに登録されることを依然として確認する必要があります。接続の関連付けと同様に、コンテナにとっての問題はトランザクションの境界が越えられたことをどのようにして知るかにあります。
接続がトランザクション(がある場合)に登録される必要があることをコンテナに通知することはリソース・アダプタに任されているため、J2CAの遅延トランザクション登録最適化はこの問題を扱っています。ただし、遅延トランザクション登録はオプションです。OC4JはJ2CAの接続のラッピングを提供し、リソース・アダプタが遅延登録をサポートしない場合に接続が正しく登録されることを保証します。
アプリケーション・コンポーネントがJ2CAのリソース・アダプタを通して接続を取得するとき、OC4Jはコネクション・ファクトリによって返される接続ハンドルの周りにラッパー・オブジェクトを作成します。実際にアプリケーションに返されるものはラッパー・オブジェクトです。リソース・アダプタによって提供される接続をラップすることにより、コンテナは接続ハンドルが、現在のトランザクションのコンテキストと接続の共有の有効範囲にとって適切な物理接続と関連付けられていることを保証するために介入できます。
OC4Jは、すべての接続ハンドルを接続ハンドル・プロキシでラップして、接続の関連付けを行います。接続ハンドルは、接続ハンドルが実装されているインタフェースにのみキャストできます。接続ハンドルを具体クラスにキャストしようとすると、ClassCastException例外が発生します。
コネクタの接続ラッパー・クラスは、リソース・アダプタの接続ハンドルと同じインタフェースを実装します。それぞれのラッパー・オブジェクトはリソース・アダプタによって返される実際の接続ハンドル・オブジェクトを参照して作成されます。すべてのメソッド・コールは、基礎となる参照される接続ハンドルに委譲される前にラッパーにインターセプトされます。
たとえば、コネクタの接続ラッパーのいくつかのメソッド・コールはインターセプトされ、接続ハンドルが現在のトランザクションのコンテキストに正しく登録された管理接続に関連付けられていたことが確認されます。このことは、新しい管理接続への接続ハンドルの再度の関連付けを伴う場合もあり、また単に現在関連付けられている管理接続が現在のトランザクションのコンテキストに登録されていることを確認する場合もあります。コネクタの接続ラッパーはその後、メソッド・コールを基礎となる接続ハンドル・オブジェクトに委譲します。
この項のシナリオでは接続の関連付けを使用するいくつかの問題を説明します。
アプリケーションはトランザクションの外部で接続を取得し、その接続をトランザクションの有効範囲内で使用します。
アプリケーションはOracle J2CAから接続を取得します。
アプリケーションはUserTransaction.begin()
を使用してトランザクションを開始します。
アプリケーションは登録されたトランザクション内で別のリソースを使用します。
アプリケーションはトランザクションの有効範囲内でJ2CAの接続を使用します。
J2CA接続はトランザクションの有効範囲外で作成されたので、トランザクションに関連付けられません。これは基本的でないトランザクションの結果をもたらし、トランザクションに登録された作業はロールバックされる可能性があり、J2CA接続に対して実行された作業はコミットされる場合があります。また逆の場合もあります。
アプリケーションは接続が登録され、後に別のトランザクションのコンテキストにおいて使用されるように、トランザクションの有効範囲内でエミュレートされたJ2CA接続を取得します。
アプリケーションはグローバル・トランザクションを開始します。
アプリケーションは必要なtx
属性を持つステートフル・セッションBeanのメソッドをコールします。トランザクションはすでにスレッドに関連付けられているので、EJBコンテナは新しいトランザクションを開始しません。
エミュレートされたJC2A接続はこのメソッドにおいて取得され、いくつかのデータの変更のために使用されます。作成されたときに接続はトランザクションに登録され、(閉じていない)インスタンスにキャッシュされます。
トランザクションはメソッドの起動の前に配置されていたので、メソッドはトランザクションをコミットしないで戻ります。
アプリケーションはRequiresNew
のtx
属性を持つ同じステートフル・セッションBeanの異なるメソッドをコールします。これは既存のトランザクションの関連付けを一時停止し、メソッドの起動のための新しいトランザクションを開始することをEJBコンテナに強制します。
Beanは以前のメソッドの起動において使用されたものと同じ接続ハンドルを使用します。
この時点で接続ハンドルは、異なるトランザクションの有効範囲内にあった最初のメソッドの起動用と同じ1pc物理接続をまだ使用しているので、エミュレートされたJ2CA接続に対して実行された第2のメソッドの起動でのすべての作業は、元の一時停止されたトランザクションのかわりに行われたのであり、第2のメソッドの起動時に使用された新しいトランザクションのかわりに行われたのではありません。接続ハンドルは、トランザクションのコンテキストに変更があることを認識して、ハンドルによって使用されている物理接続をスワップ・アウトする必要があります。
このシナリオは第1のトランザクションがコミットする一方で第2のトランザクションがロールバックする可能性があるので正しくない結果をもたらします。一貫性のない結果を防ぐために、Oracle J2CAは現在、エミュレートされた接続が登録されているトランザクションのコンテキストの一時停止で例外をスローします。これによりOC4Jユーザーは、前述した正当なシナリオを実行することができません。
注意: XA接続はXAリソースに対して開始と終了のコールを送り、リソースは接続をトランザクションに関連付けたり関連をなくしたりするため、このシナリオはエミュレートされた接続においてのみ問題となります。エミュレートされた接続では、OC4Jはこれらの開始と終了のコールをリソースに送ることができないので、OC4Jは物理接続のトランザクションのコンテキストへの関連付けを保持し、トランザクションのコンテキストに従っていかなる呼出しにも応じられるように物理接続を適切にスイッチする必要があります。 |
接続の共有のために同じ物理接続を指している2つの接続ハンドルは、後に異なるトランザクションのコンテキストにおいて使用されます。このシナリオは、エミュレートされた接続かエミュレートされていない接続かのどちらかを使用します。
アプリケーションはRequired
のtx
属性を持つEJB Aのメソッドをコールします。EJBコンテナは新しいトランザクションを開始します。
EJB Aはresource1
への接続を取得し、その接続をトランザクションの有効範囲内で使用します。したがって、接続はトランザクションに登録されます。接続は後の使用のためにキャッシュされます。
EJB AはRequired
のtx
属性を持つEJB Bのメソッドをコールします。トランザクションはすでにスレッドに関連付けられているので、新しいトランザクションは作成されません。
EJB Bもまたresource1
への接続を取得し、その接続はキャッシュされます。接続の共有のためにEJB Aの接続ハンドルとEJB Bの接続ハンドルは同じ物理接続を指します。
両方のメソッドの起動の完了は成功し、トランザクションはコミットします。この時点で、トランザクションはコミットし、両方の接続ハンドルは同じ物理接続を指しています。
後に、アプリケーションはRequired
のtx
属性を持つEJB Aの異なるメソッドをコールします。EJBコンテナは新しいトランザクションを開始します。
EJB Aは新しく作成されたトランザクションの有効範囲内で以前にキャッシュされた接続を使用します。
注意: シナリオ1の場合と同様に、現在接続はトランザクションに関連付けられていません。この使用例では登録の問題が解決され、接続がトランザクションに正しく登録されることを仮定しています。 |
EJB Aが前述のメソッドの起動を処理している同じときに、別のアプリケーションのスレッドがNever
のtx
属性を持つEJB Bのメソッドをコールします。Never
のtx
属性のために、メソッドはnullトランザクションのコンテキストにおいて起動されます。
EJB Bはトランザクションに参加しない一方、以前にキャッシュされた接続を使用します。
この時点で、EJB AとEJB Bは同じ物理接続を指す2つの個別の接続ハンドルを使用しています。物理接続はEJB Aのトランザクションに登録されますが、トランザクションの関連付けなしにEJB Bによっても使用されています。接続はEJB Aのトランザクションに登録されているので、EJB Bによってその接続ハンドルになされたすべての作業はEJB Aのトランザクションの一部となりますが、これは明らかに間違いです。
このケースは、XA接続とエミュレートされた接続の両方に対して有効になるシナリオ2とは異なっています。また、一時停止の発生においてエミュレートされた接続から例外がスローされるシナリオ3のメカニズムはこのケースの正しくない結果を防ぐことはできません。