我有以下MessageDrivenBean:
@MessageDriven(mappedName = "jms/...", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "5"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "1000")
})
public class MyMessageListener implements MessageListener {
@Resource
private MessageDrivenContext context;
@Override
@TransactionAttribute(REQUIRED)
public void onMessage(Message message) {
}
}
在onMessage
方法中,我做了一些在这里不重要的处理。在某些情况下,我想放弃处理。在那种情况下,我想将事务标记为仅回滚,并且不想重试处理。
至少在Glassfish 3.1.1上,如果我在context.setRollbackOnly()
上调用MessageDrivenContext
并结束处理而不抛出异常,则会在非常非常短的时间间隔内无限地重新传递消息。所以这对我来说是没有选择的。
如果我抛出RuntimeException
,则会按照我的指定重新传递该消息。它以1秒的间隔重新传送5次。但在我的情况下,我根本不想重试处理。
如果我只是结束处理而不抛出任何异常并且没有调用context.setRollbackOnly()
,那么就像人们所期望的那样提交事务。但是我需要回滚事务,因为我可能已经改变了一些JPA实体。
我的问题是:如何在不触发消息重新传递的情况下将事务标记为仅回滚?
答案 0 :(得分:1)
我看到两个选项:
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
注释bean,使用bean管理的事务而不使用AUTO_ACKNOWLEDGE(在MDB中显式确认消息)。如果您的MDB是更大的XA交易的一部分,则不是一个选项,您将没有机会影响全局交易结果。getJMSRedelivered()
标记,然后丢弃重新传递的邮件。这里的问题是,在重新传递时你不知道它是否是你应该忽略的重新传递(你说在某些情况下你确实想重试处理) - 你必须暂时存储(在数据库或缓存中)id处理失败的消息,因此您知道是否可以安全地忽略它们。