1

有一个 MDB 和一系列无状态 EJB 来处理消息(WAS 7.0、Java EE 5、EJB 3.0、JPA)。

序列(使用 CMT):

  • MDB 接受消息
  • MDB 使用消息详细信息持久化实体
  • MDB 调用 EJB 1 传递实体 ID,
  • EJB1 对消息进行处理,这取决于 EJB1 调用是否成功
  • 传递 ID 的 EJB2 或 EJB5
  • EJB2 做了它的一部分......

依此类推,直到最后一个 EJB(运行时间为几分钟)。

所有这些都发生在一个事务中:因此,如果在 EJB4 中抛出了一些东西 - 该事务中之前发生的所有事情都将被回滚。我尝试将 REQUIRES_NEW 用于所有后续调用,但似乎先前调用中的更改对于后续调用不可见。此外,事务变得很长,有时甚至超时。

我想有单独的,独立的交易:

  • 接收和持久消息
  • EJB1中的B处理
  • EJB2 中的 C 处理

.... 因此,如果 EJB2 执行失败,则消息应保留在 DB 中,并且 EJB1 中的执行结果也应保留。

所以主要问题是,使用 CMT - 是否可以为序列进行简短独立的交易?

多一点

  • 源自 MDB 的事务能否独立于对 EJB1 的调用结果提交?此外——在调用 EJB1 之前提交..?
  • 在对具有 REQUIRES_NEW 属性的 EJB1 方法的调用中,对 MDB 内的实体所做的更改是否可以看到?
  • 除了 BTM 或 WorkManager 之外,还有其他方法可以实现目标吗?
4

1 回答 1

1

REQUIRES_NEW 应该没有任何问题。

如果你有这个:

@EJB(..)
EJB1 ejb1;
@EJB(..)
EJB2 ejb2;

public void onMessage(Message message) {
    Thing thing = getThingFromMessage(message);

    persistThingStuff(thing);
    ejb1.doThingStuffWithRequiresNew(thing);
    ejb2.doThingStuffWithRequiresNew(thing);
}

这应该只是工作(tm)有一个警告。

如果ejb2 抛出异常,ejb1 的工作将被提交,但persistThingStuff 将回滚。

但是,如果您执行以下操作:

public void onMessage(Message message) {
    Thing thing = getThingFromMessage(message);

    persistThingStuff(thing);
    ejb1.doThingStuffWithRequiresNew(thing);
    try {
        ejb2.doThingStuffWithRequiresNew(thing);
    } catch (Throwable t) {
        youBetterLogThis();
    }
}

这应该可以防止任何异常破坏 MDB 的工作,但是如果 EJB2 长时间运行,则 MDB 完成的任何工作仍处于挂起状态并处于打开的事务中,等待它。

为了解决很多这些问题,我们有一个实用的 EJB 函数:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public <T extends Runnable> T runInTransaction(T runner) {
    runner.run();
    return runner;
}

那么我们不一定要为此标注具体的方法。

@EJB(...)
UtilEJB utilEjb;

public void onMessage(Message message) {
    final Thing thing = getThingFromMessage(message);

    utilEjb.runInTransaction(new Runnable() {
        public void run() {
            persistThingStuff(thing);
        }
    });
    ejb1.doThingStuffWithRequiresNew(thing);
    try {
        ejb2.doThingStuffWithRequiresNew(thing);
    } catch (Throwable t) {
        youBetterLogThis();
    }
}

这将立即提交 MDB 工作,甚至在 EJB1 之前。

于 2013-01-16T01:26:14.050 回答