2

今天我在 EJB 中发现了一些意想不到的行为。我有默认事务属性 ( REQUIRED) 的 MDB 和事务属性设置为 的 SLSB REQUIRES_NEW。我的 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. 消息驱动 beanonMessage(Message)被调用。
  2. 消息驱动 bean 成功执行一些动作然后调用B.process(Message)方法。
  3. B发生了一些不好的事情RuntimeException并被抛出。
  4. RuntimeExceptionEJBException被消息驱动bean包裹并成功捕获。
  5. 消息驱动的 beanonMessage(Message)方法已完全执行,但它的事务被标记为回滚

任何人都可以解释这种行为吗?提前致谢。

4

2 回答 2

1

正如@gkuzmin 所说。

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

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

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

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

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

注意粗体部分。正如您所料,它不是 S 超类的业务方法。

于 2013-04-22T12:15:51.147 回答
0

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

于 2012-09-11T13:17:55.770 回答