基本上,我有一个JMS队列和一个MDB,用于从JMS队列中收集消息,对它们进行一些处理,然后通过JPA将消息持久化到数据库中.我将负责将消息持久保存到数据库中的方法标记为要在新事务中启动:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void create(T entity)
{
try
{
getEntityManager().persist(entity);
}
catch(Exception e)
{
throw new RuntimeException("DB Exception");
}
}
如果交易被回滚,是否会自动退休直到交易完成?如果没有,如何启用?
解决方法:
如果异常传播到MDB,则事务将不会提交,消息将不会被确认为已接收,并将被重试.根据EJB 3.1规范:
Message acknowledgment is automatically handled by the container. If
the message-driven bean uses container-managed transaction
demarcation, message acknowledgment is handled automatically as a part
of the transaction commit.
我对Weblogic并不熟悉,但是应该有一个JMS队列参数,用于设置重试次数,重试间隔等,直到消息被丢弃或放入未传递的队列为止.
但是通常最好在MDB中捕获该异常,因为从MDB抛出RuntimeException会导致该Bean被容器丢弃.根据EJB 3.1规范:
Message-driven beans should not, in general, throw RuntimeExceptions.
A RuntimeException that is not an application exception thrown from
any method of the message-driven bean class (including a message
listener method and the callbacks invoked by the container) results in
the transition to the “does not exist” state.
例如,最好具有:
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();
}
}
}