2

トランザクションの開始を担当するEJBコンポーネントに問題があります。Jboss5.01を使用しています。

基本的に、特定のトランザクションがコミットされた後に、特定のコードを実行したいと思います。特定のコードには、独自のトランザクションを作成するEJBコンポーネントの呼び出しも含まれます。

前のトランザクションがコミットされた後にコードが実行されることを確認するために、同期コンポーネントをトランザクションコンポーネントに登録しました。

Transaction tx = transactionManager.getTransaction();
tx.registerSynchronization(new CallbackSynchronization());

Synchronizaton実装は基本的に次のことを行います。

class CallbackSynchronization implements Synchnronization {

    private AccountService service;  // This is a Stateless session bean

    public CallbackSynchronization(AccountService service) {
        this.service   = service;
    }

    public afterCompletion(int status) {
        if(Status.STATUS_COMMITTED == status) {
            service.deleteAccounts();
        }
    }
}

問題は、電話をかけるとservice.deleteAccounts()、トランザクションがアクティブではないことを最終的に通知する例外が発生することです。

そして、これは私を混乱させるものです。でマークされたメソッドを持つEJB@TransactionAttribute(TransactionAttributeType.REQUIRED)は、アクティブでない場合に新しいトランザクションを作成します(REQUIREDはJBOSSのデフォルトです)。

それでは、なぜ「トランザクションがアクティブではない」というメッセージが表示されるのですか?

どうもありがとう、

ヤニフ

4

1 に答える 1

3

問題は、開始した元のトランザクションがまだスレッドに関連付けられていることです (COMMITTED ステータスであっても)。Transactionを使用する場合とTransactionManagerを使用する場合の大きな違いの 1 つは、後者のcommit( ) メソッドとrollback()メソッドがスレッドからトランザクションの関連付けを解除することです。両方のメソッドの javadoc から引用するには:

このメソッドが完了すると、スレッドはトランザクションに関連付けられなくなります。

これに対処するには 2 つの方法があります (そして、私はそれらを非常に生の方法で概説しているので、少し改良する必要があるかもしれません)。

オプション 1: トランザクション マネージャーに対してロールバックまたはコミットを発行します (失敗するため、try ブロックで)。

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { transactionManager.rollback(); } catch (Throwable t) {}
    service.deleteAccounts();
  }
}

オプション 2: 新しいトランザクションを開始します。これは、トランザクションを事前に開始することで EJB の REQUIRED 属性を満たしますが、固執してそれを管理する必要があります。

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { 
      transactionManager.begin();
      service.deleteAccounts();
      transactionManager.commit();
    } catch (Exception e) {
        // ... handle exception here
    }
  }
}

オプション 3: 最もクリーンなオプションは、EJB メソッドをREQUIRES_NEWとしてマークすることです。これにより、EJB コンテナーが新しいトランザクションを開始するようになります。

于 2012-02-01T14:30:33.360 に答える