ランタイムに関する規約には,コンテナ側の責任とJPAプロバイダ側の責任があります。
アプリケーションで使用するエンティティマネージャが,トランザクションスコープの永続化コンテキストを使用するように定義されているか,拡張永続化コンテキストを使用するように定義されているかは,JPAプロバイダには伝わりません。JPAプロバイダでの責任は,コンテナが要求したときにエンティティマネージャを作成し,トランザクションからトランザクションの決着の通知を受け取るためのSynchronizationをトランザクションに登録することです。
JPAプロバイダは,トランザクションにSynchronizationを登録したり,トランザクションをロールバックにマークしたりするために,TransactionSynchronizationRegistryインタフェースを使用できます。TransactionSynchronizationRegistryのインスタンスは,JNDIを使用して「java:comp/TransactionSynchronizationRegistry」という名前でルックアップできます。
インタフェース定義を次に示します。
package javax.transaction;
/**
* このインタフェースは,JPAプロバイダやリソースアダプタなど,
* アプリケーションサーバのシステムレベルのコンポーネントから使用する
* ためのものです。
* このインタフェースを使って,
* 特別な順序で呼ばれるシンクロナイゼーションの登録,
* 現在のトランザクションへのリソースオブジェクトの登録,
* 現在のトランザクションのコンテキストの取得,
* 現在のトランザクションのステータスの取得,
* 現在のトランザクションをロールバックにマークできます。
*
* このインタフェースはステートレスなサービスオブジェクトとして,
* アプリケーションサーバによって実装されます。
* 同じオブジェクトを複数のコンポーネントからマルチスレッドセーフに
* 使用できます。
*
* 標準的なアプリケーションサーバでは,このインタフェースを実装した
* インスタンスは,JNDIを使用して標準的な名前でルックアップできます。
* 標準的な名前は
* 「java:comp/TransactionSynchronizationRegistry」です。
*/
public interface TransactionSynchronizationRegistry {
/**
* このメソッドを呼び出した時に現在のスレッドに関連づいている
* トランザクションを表現する一意のオブジェクトを返します。
* このオブジェクトのhashCodeとequalsメソッドは
* オーバーライドされており,
* ハッシュマップのキーとして使用できます。
* トランザクションが存在しない場合には,nullを返します。
*
* 同じアプリケーションサーバの同じトランザクションコンテキスト内で
* このメソッドが呼ばれて返されたオブジェクトは,すべて同じhashCodeを
* 持ち,equalメソッドでの比較結果はtrueとなります。
*
* toStringメソッドは,トランザクションコンテキストの情報を人が
* 読みやすい形の文字列として返します。
* ただし,toStringで返される文字列のフォーマットは規定されていません。
* また,toStringの結果に関して,バージョン間での互換性は
* 保障されていません。
*
* 取得したオブジェクトがシリアライズできる保障はなく,
* JavaVMの外に出したときの動作は規定されていません。
*
* @return このメソッドが呼ばれたときにスレッドに関連づいている
* トランザクションを一意に表現するオブジェクト
*/
Object getTransactionKey();
/**
* このメソッドを呼び出した時のスレッドに関連づいているトランザクション
* のリソースマップに,オブジェクトを追加またはリプレースします。
* マップのキーは,コンフリクトが発生しないように,
* このメソッドを呼び出す側で定義されたクラスである必要があります。
* キーとして使用するクラスは,マップのキーとして適切なhashCodeとequals
* メソッドを持っている必要があります。
* マップのキーや値が,このクラスによって評価されたり,使用されたりする
* ことはありません。
* このメソッドの一般的な規約は,Mapのputメソッドと同じで,
* キーはnull以外にする必要がありますが,値はnullにすることもできます。
* すでにキーに関連づいた値が存在する場合,その値は置き換えられます。
*
* @param key マップのエントリのキー
* @param value マップのエントリの値
* @exception IllegalStateException アクティブなトランザクションが
* 存在しない場合
* @exception NullPointerException 引数のキーがnullである場合
*/
void putResource(Object key, Object value);
/**
* このメソッドを呼び出した時のスレッドに関連づいているトランザクション
* のリソースマップから,オブジェクトを取り出します。
* キーは,同じトランザクション内で,事前にputResourceメソッドに
* 指定したオブジェクトと同じである必要があります。
* 指定されたキーが現在のリソースマップに存在しない場合は,
* nullを返します。
* このメソッドの一般的な規約は,Mapのputメソッドと同じで,
* キーはnull以外にする必要がありますが,値はnullにすることもできます。
* マップにキーが格納されていない場合や,キーに対してnullが格納
* されている場合には,返り値はnullになります。
* @param key マップのエントリのキー
* @return キーに関連づけられた値
* @exception IllegalStateException アクティブなトランザクションが
* 存在しない場合
* @exception NullPointerException 引数のキーがnullである場合
*/
Object getResource(Object key);
/**
* 特別な順序で呼ばれるシンクロナイゼーションのインスタンスを登録します。
* このメソッドで登録したSynchronizationのbeforeCompletionは,
* すべてのSessionSynchronization.beforeCompletionや,
* トランザクションに直接登録された
* Synchronization.beforeCompletionが呼ばれたあとで,
* 2フェーズコミット処理が開始される前に呼び出されます。
* 同じように,このメソッドで登録した
* SynchronizationのafterCompletionは,
* 2フェーズコミット処理が完了したあとで,
* すべてのSessionSynchronization.afterCompletionや,
* トランザクションに直接登録されたSynchronization.afterCompletionが
* 呼ばれる前に呼び出されます。
*
* beforeCompletionは,このメソッドを呼び出した時にスレッドに
* 関連づいていたトランザクションのコンテキストで呼び出されます。
* beforeCompletionでは,コネクタなどのリソースへのアクセスは
* 許可されていますが,タイマーサービスやビーンのメソッドなどの
* ユーザコンポーネントへのアクセスは許可されていません。
* これは,呼び出し側によって管理されているデータや,
* registerInterposedSynchronizationで登録された
* ほかのSynchronizationによって
* すでにフラッシュされたデータを変更してしまうおそれがあるためです。
* 一般的なコンテキストは,registerInterposedSynchronizationを
* 呼び出したコンポーネントのコンテキストになります。
*
* afterCompletionが呼び出される時のコンテキストは定義されていません。
* なお,ユーザコンポーネントへのアクセスは許可されていません。
* また,リソースをクローズすることはできますが,
* リソースに対するトランザクショナルな操作はできません。
*
*トランザクションがアクティブでない場合にこのメソッドが呼び出されたとき,
* IllegalStateExceptionがスローされます。
*
* このメソッドが2フェーズコミット処理の開始後に呼び出された場合は,
* IllegalStateExceptionがスローされます。
*
* @param sync 登録するSynchronizationのインスタンス
* @exception IllegalStateException アクティブなトランザクションが
* 存在しない場合
*/
void registerInterposedSynchronization(Synchronization sync);
/**
* このメソッドを呼んだ時にスレッドに関連づいているトランザクション
* のステータスを返します。
* このメソッドの返り値は,
* TransactionManager.getStatus()の結果と同じです。
*
* @return このメソッドを呼んだときにスレッドに関連づいている
* トランザクションのステータス
*/
int getTransactionStatus();
/**
* このメソッドを呼んだ時にスレッドに関連づいているトランザクション
* がロールバックされるようにマークします。
*
* @exception IllegalStateException アクティブなトランザクションが
* 存在しない場合
*/
void setRollbackOnly();
/**
* このメソッドを呼んだ時にスレッドに関連づいているトランザクション
* がロールバックするようにマークされているかどうかを返します。
*
* @return ロールバックするようにマークされている場合はtrue
* @exception IllegalStateException アクティブなトランザクションが
* 存在しない場合
*/
boolean getRollbackOnly();
}