2

次のシナリオでは、callSessionBean2()で開始されたトランザクションはどのように動作しますか?中断されていますか?SessionBean2で例外がスローされた場合はどうなりますか?SessionBean2は、データベースと通信せず、LDAP経由でADサーバーとのみ通信するため、BEANトランザクション管理タイプでセットアップされました。

デプロイメントの数週間後に実稼働サーバーでSessionBean2の呼び出しがハングし始め、トランザクションのタイムアウトが唯一のエラーであるという問題が発生しているため、質問しています。この設定は悪いことかもしれないと思いましたが、誰かがこれに光を当てることができますか?

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class SessionBean1 {
    @Inject private SessionBean2 sessionBean2;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void callSessionBean2(){
        sessionBean2.doThingsThatMightCauseException();
    }
}

@Singleton
@TransactionManagement(TransactionManagementType.BEAN)
public class SessionBean2 {
    public void doThingsThatMightCauseException(){...}
}
4

2 に答える 2

2

EJB 3.1仕様(§13.6.1)で宣言されているように、呼び出し元のトランザクションは一時停止されます。

クライアントリクエストがトランザクションT1に関連付けられていて、インスタンスがトランザクションに関連付けられていない場合、コンテナはクライアントのトランザクションの関連付けを一時停止し、指定されていないトランザクションコンテキストでメソッドを呼び出します。メソッドが(関連するインターセプターメソッドとともに)完了すると、コンテナーはクライアントのトランザクションの関連付け(T1)を再開します。

したがって、に関連付けられたトランザクションSessionBean1は一時停止され、いずれの場合でもスローされた例外SessionBean2は、適切なセマンティクス(つまり、CMTセッションによって処理される)を使用して、呼び出し元のBeanによって処理されます。

あなたのコードは正しいですが、私はむしろ使用したいと思います:

@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class SessionBean2 {
    public void doThingsThatMightCauseException(){...}
}

同じ効果に。

発生している問題は、アノテーションに関連している可能性があります@Singleton。これは、§4.8.5.3および§4.8.5.3によると、Beanのデフォルトは次のとおりです。

@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Lock(LockType.WRITE)

これにより、の呼び出しがシリアル化され、doThingsThatMightCauseExceptionランダムになりConcurrentAccessTimeoutExceptionます。同時アクセスタイムアウトはを介して構成できますが@AccessTimeout、(シリアル化された)doThingsThatMightCauseExceptionアクセス遅延がCMTトランザクションに定義されたタイムアウトを超えると、トランザクションタイムアウトが発生します(関連付けられたCMTトランザクションSessionBean1は一時停止されますが、クロックはカウントされます... )。

まとめ:

アクセスロックをオンに変更するには、(共有状態に適切な注意を払って)次のものを使用する必要がありますdoThingsThatMightCauseException

@Lock(LockType.READ)
public void doThingsThatMightCauseException(){...}

これにより、アクセスのシリアル化が削除され、タイムアウトの問題が解決されることが期待されます。

それでもタイムアウトが発生する場合は、に含まれる操作の速度が遅いことに関係していdoThingsThatMightCauseExceptionます。この場合、次のいずれかを行う必要があります。

  • トランザクションの外部でメソッドを呼び出し、
  • またはCMTトランザクションタイムアウトを変更します(AS固有の構成/展開で)
  • またはBMTに変換SessionBean1して、レバレッジUserTransaction.setTransactionTimeout
于 2013-01-04T11:28:40.120 に答える
-2

私のアドバイスは、すべてのトランザクションを手動で管理することです。Java 6 EE仕様によると:

コンテナ管理のトランザクション境界を使用するエンタープライズBeanは、コンテナのトランザクション境界の境界に干渉するトランザクション管理メソッドを使用してはなりません。このようなメソッドの例としては、java.sql.Connectionのcommit、setAutoCommit、およびrollbackメソッド、またはjavax.jms.Sessionのcommitおよびrollbackメソッドがあります。トランザクションの境界を制御する必要がある場合は、アプリケーション管理のトランザクションの境界を使用する必要があります。

コンテナ管理のトランザクション境界を使用するエンタープライズBeanも、javax.transaction.UserTransactionインターフェースを使用してはなりません。

于 2013-01-04T09:34:44.193 に答える