今天我在 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){
...
}
}
有问题的任务流程如下所示:
- 消息驱动 bean
onMessage(Message)
被调用。 - 消息驱动 bean 成功执行一些动作然后调用
B.process(Message)
方法。 B
发生了一些不好的事情RuntimeException
并被抛出。RuntimeException
EJBException
被消息驱动bean包裹并成功捕获。- 消息驱动的 bean
onMessage(Message)
方法已完全执行,但它的事务被标记为回滚。
任何人都可以解释这种行为吗?提前致谢。