EJB エンジンは、X/Open XA 仕様に基づいて 2 フェーズ コミット トランザクション管理を完全にサポートしています。EJB エンジンは、フラット トランザクションをサポートしていますが、ネストされた (子) トランザクションはサポートしていません。
|
メモ JRun では、トランザクションの実行中に新しいトランザクションを開始できますが、 これは真のネスト トランザクションではありません。つまり、外部トランザクションの 後のロールバックは内部トランザクションのロールバックとはなりません。 |
コンテナ管理トランザクション (暗黙的トランザクション、CMT) とクライアントまたは Bean 管理トランザクション (明示的トランザクション、BMT) が両方ともサポートされています。
EJB を公開する場合は、公開記述子に指定されているように、トランザクション属性によりトランザクションに必要なものを指定します。JRun では、要素を使用してトランザクション属性を設定できます。
container-transaction
あるメソッドが特定のトランザクション動作を必要とする一方で、同じクラスの別のメソッドが異なるトランザクション動作を必要とする場合があります。メソッド レベルのトランザクション属性は Bean の仕様に従わず、
methodname.ejb.transactionAttribute の形式で env-entry を使用します。次の EJB サンプル 4b からの例では、ejb-entries を使用してトランザクション属性を指定します。
<env-entry>
<env-entry-name>spend.ejb.transactionAttribute</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>required</env-entry-value> </env-entry> <env-entry> <env-entry-name>save.ejb.transactionAttribute</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>mandatory</env-entry-value> </env-entry>
次の例は、<container-transaction> 要素における同等の設定を示します。
...
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BalanceBean</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Supports</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>BalanceBean</ejb-name>
<method-name>save</method-name>
</method>
<trans-attribute>Mandatory</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>BalanceBean</ejb-name>
<method-name>spend</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
...
</assembly-descriptor>
これらの設定の結果、save メソッドには Mandatory が、spend メソッドには Required が設定されます。
トランザクション属性はエンティティ Bean の create、find、および remove メソッドに付加することもできます。属性を設定するときは、リモートおよびホーム インターフェイスに表示される名前を使用する必要があります。
env-entry の有効な属性の一覧については、JRun JavaDocs ファイルに付属する EjiptProperties API マニュアルを参照してください。すべての公開記述子エントリの一覧については、EJB バージョン 1.1 の仕様書を参照してください。
CMT を使用すると、Bean に代わってコンテナがトランザクションを開始してコミットまたはロールバックします。CMT を利用するには、Bean (またはメソッド) のトランザクション属性を次のいずれかに設定する必要があります。
required
RequiresNewMandatoryコンテナが CMT の例外を処理する方法は、次のように、例外がアプリケーション例外 (確認済みの例外) かシステム例外 (未確認の例外) かによって異なります。
java.lang.RuntimeException または java.rmi.RemoteException を拡張する例外を除くすべての例外。アプリケーション例外が発生すると、コンテナからクライアントに例外が返され、次のように、クライアント トランザクションがロールバックされる場合とされない場合があります。
setRollbackOnly メソッドを呼び出したかどうかをチェックします。呼び出していれば、コンテナはトランザクションをロールバックして再び例外を返します。呼び出していなければ、再び例外を返します。java.lang.RuntimeException または java.rmi.RemoteException (EJBException を含む) を拡張するすべての例外。コンテナによって EJB メソッドがロールバックされ、次のように、クライアント トランザクションがロールバックされる場合とされない場合があります。RemoteException を返します。例外と CMT のロールバックの関係の詳細については、EJB バージョン 1.1 の仕様書のトランザクションに関する章を参照してください。
あるトランザクションに関係したメソッドから例外が返されると、サーバーからも例外が返され、トランザクションが自動的にロールバックされる場合があります。メソッドで発生した最初の例外はクライアントに対して返されます。
このトランザクション管理によって、トランザクションを完全に制御し、クライアントから管理できます。セッション Bean の場合は、Bean 自体から管理できます。
クライアントはトランザクションを明示的に開始するか、コミットするか、またはロールバックすることを選択できます。次のスニペットは、クライアント区分トランザクションを示します。明示的な呼び出しによって、トランザクションを開始して、コミットまたはロールバックすることに注意してください。
public void save(final int amount) {
try{
final UserTransaction transaction =
(UserTransaction)_context.lookup
("javax.transaction.UserTransaction");
transaction.begin();
try {
_balance.save(amount);
}
catch (Exception exception){
transaction.rollback();
throw exception;
}
transaction.commit();
return;
}
catch (RemoteException remote){
throw new RuntimeException(remote.toString());
}
catch (Exception exception){
throw new RuntimeException(exception.toString());
}
}
また、トランザクション内で呼び出されるメソッドについて、適切なトランザクションを設定する必要があります。
Bean 管理トランザクション (BMT) はセッション Bean にのみ使用でき、エンティティ Bean では使用できません。BMT を使用する場合、次のように、Bean のプロパティ ファイルにトランザクション属性を設定する必要があります。
<transaction-type>Bean</transaction-type>
次のスニペットは、どのようにメソッドを構築するかを示します。
public void spend(final int value) throws RemoteException {
if (_value - value < _min){
throw new RuntimeException("Min limit reached");
}
if (_balance != null){
final UserTransaction transaction = _context.getUserTransaction();
transaction.begin();
try {
_balance.spend(value);
}
catch (final RemoteException remote){
transaction.rollback();
throw remote;
}
transaction.commit();
}
_value -= value;
}
アプリケーション例外が返されると、明示的トランザクションは自動的にロールバックされません。ただし、未確認の例外の場合は、明示的なトランザクションにロールバックのマークが付けられ、TransactionRolledbackException が返されます。