3

基本上,我有一个 JMS 队列和一个 MDB 来从 JMS 队列中收集消息,对它们进行一些处理,然后通过 JPA 将消息持久化到数据库中。我标记了负责将消息持久化到 DB 中的方法,以便在新事务中启动:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void create(T entity)
{
    try
    {
        getEntityManager().persist(entity);
    }
    catch(Exception e)
    {
        throw new RuntimeException("DB Exception");
    }
}

如果事务回滚,是否会自动退出,直到事务完成?如果没有,如何启用它?

4

1 回答 1

4

如果异常传播到MDB,则事务将不会提交,消息将不会被确认为已接收并且将被重试。从 EJB 3.1 规范:

消息确认由容器自动处理。如果消息驱动 bean 使用容器管理的事务划分,消息确认将作为事务提交的一部分自动处理。

我不熟悉,Weblogic但应该有一个 JMS 队列参数,用于设置重试次数、重试间隔等,直到消息被丢弃或放入未传递的队列。

但通常最好在 bean 中捕获异常,MDB因为RuntimeException从结果中抛出MDB的 bean 被容器丢弃。从 EJB 3.1 规范:

一般来说,消息驱动的 bean 不应该抛出 RuntimeExceptions。

不是从消息驱动 bean 类的任何方法(包括消息侦听器方法和容器调用的回调)抛出的不是应用程序异常的 RuntimeException 会导致转换到“不存在”状态。

例如,最好有:

public class MyMDB implements MessageListener {

  @Resource
  private MessageDrivenContext context;

  public void onMessage() {
     try {
        //some other processing
        someService.create(entity);
     }
     catch(Exception e) {
        //mark the message as undelivered
        context.setRollbackOnly();
     }
  }
}
于 2013-04-23T18:51:20.973 回答