2

在 callSessionBean2() 中启动的事务在以下场景中将如何表现?是否暂停?如果在 SessionBean2 中抛出异常会发生什么?SessionBean2 设置为 BEAN 事务管理类型,因为它不与任何数据库通信,仅通过 LDAP 与 AD 服务器通信。

我之所以问,是因为在部署后的几周内,我在生产服务器中遇到问题,对 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在任何一种情况下抛出的异常都将由调用 bean 处理,具有适当的语义(即由 CMT 会话处理)

您的代码是正确的,但我宁愿使用:

@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,但如果(序列化)访问延迟超过为 CMT 事务定义的超时,则会导致事务超时doThingsThatMightCauseException(请记住,与之关联的 CMT 事务SessionBean1被挂起,但时钟仍在计数...... )。

总结一下:

您需要(适当注意共享状态)通过以下方式更改访问锁定doThingsThatMightCauseException

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

这将删除访问序列化,希望能解决您的超时问题。

如果您仍然遇到超时,这将与包含在doThingsThatMightCauseException. 在这种情况下,您需要:

  • 在任何事务之外调用该方法,
  • 或更改 CMT 事务超时(在 AS 特定配置/部署中)
  • 或转换SessionBean1为 BMT,从而利用UserTransaction.setTransactionTimeout
于 2013-01-04T11:28:40.120 回答
-2

My advise is to manage all transaction manually. According to Java 6 EE specification:

Enterprise beans that use container-managed transaction demarcation must not use any transaction-management methods that interfere with the container’s transaction demarcation boundaries. Examples of such methods are the commit, setAutoCommit, and rollback methods of java.sql.Connection or the commit and rollback methods of javax.jms.Session. If you require control over the transaction demarcation, you must use application-managed transaction demarcation.

Enterprise beans that use container-managed transaction demarcation also must not use the javax.transaction.UserTransaction interface.

于 2013-01-04T09:34:44.193 回答