EJB中的嵌套事务行为

时间:2012-07-31 20:46:23

标签: java transactions ejb weblogic message-driven-bean

今天我在EJB中发现了一些意想不到的行为。我有默认事务属性(REQUIRED)的MDB和事务属性设置为REQUIRES_NEW的SLSB。我的MDB调用SLSB并捕获SLSB可以抛出的任何异常。当SLSB中出现一些真正不好的东西时,会抛出RuntimeException的某个子类。然后,为SLSB创建的新事务被标记为回滚。从我的角度来看,这是一种正确的行为。然后MDB捕获此异常并执行一些操作(例如,将消息写入日志)并重新抛出。但MDB事务也以某种方式标记为回滚,这对我来说似乎很奇怪。这种行为是否正确?

更准确地说,我可以编写一些类似于实际代码的代码,这会产生这种行为:

@MessageDriven
public class A{

@EJB
private B b;

@Overried
public void onMessage(Message msg){
...
try{
b.process(msg);
} catch (Throwable t){
logger.error("Something gone wrong",t);
}
...
}

SLSB看起来像这样:

@EJB
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class B{
public void process(Message msg){
...
}
}

有问题的任务流程如下所示:

  1. 调用了消息驱动的bean onMessage(Message)
  2. 消息驱动bean成功执行某些操作,然后调用B.process(Message)方法。
  3. B发生了一些不好的事情,RuntimeException被抛出。
  4. RuntimeExceptionEJBException包裹,并被消息驱动的bean成功捕获。
  5. 消息驱动的bean onMessage(Message)方法已完全执行, 但其事务已标记为回滚
  6. 有人可以解释这种行为吗? 提前谢谢。

2 个答案:

答案 0 :(得分:1)

正如@gkuzmin所说。

EJB 3.1规范第13.3.7.1节中的相关部分:

如果bean类具有超类,则适用以下附加规则。

  • 在超类S上指定的事务属性适用于S定义的业务方法。如果未在S上指定类级事务属性,则它等效于S上的TransactionAttribute(REQUIRED)规范。 / p>

  • 可以在由类S定义的业务方法M上指定事务属性,以便为方法M覆盖在类S上显式或隐式指定的事务属性值。

  • 如果类S的方法M覆盖由超类S定义的业务方法,则M的事务属性由上述规则确定,适用于类S

请注意粗体部分。它不是你所期望的超类S的商业方法。

答案 1 :(得分:0)

找到了解决此问题的方法。实际上,TransactionAttribute注释被放置在B bean的抽象超类上并被忽略。 WebLogic Server中的EJB运行时环境忽略来自B超类的注释,并使用默认的REQUIRED属性。如果您遇到同样的问题,我建议您阅读EJB 3.1规范中的 13.3.7.1 部分(可以下载here)。