加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在MessageDrivenBean中将事务标记为仅回滚,而不重试该消

发布时间:2020-12-15 02:30:32 所属栏目:Java 来源:网络整理
导读:我有以下MessageDrivenBean: @MessageDriven(mappedName = "jms/...",activationConfig = { @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),@ActivationConfigProperty(propertyName = "endpointExceptio
我有以下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上,如果我在MessageDrivenContext上调用context.setRollbackOnly()并结束处理而不抛出异常,则会在非常非常短的时间间隔内无限地重新传递消息.所以这对我来说是没有选择的.

如果我抛出RuntimeException,则会根据我的指定重新传递消息.它以1秒的间隔重新传送5次.但就我而言,我根本不想重试处理.

如果我只是结束处理而不抛出任何异常并且不调用context.setRollbackOnly(),那么事务就会被提交,正如人们所期望的那样.但是我需要回滚事务,因为我可能已经改变了一些JPA实体.

我的问题是:如何在不触发消息重新传递的情况下将事务标记为仅回滚?

解决方法

我看到两个选择:

>使用@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)注释bean,使用bean管理的事务,不使用AUTO_ACKNOWLEDGE(在MDB中显式确认消息).如果您的MDB是更大的XA事务的一部分,则不是一个选项,您将没有机会影响全局事务结果.>检查消息上的getJMSRedelivered()标志,然后丢弃重新传递的消息.这里的问题是,在重新传递时你不知道它是否是你应该忽略的重新传递(你说在某些情况下你确实想重试处理) – 你必须暂时存储(在数据库或缓存中)id处理失败的消息,因此您知道是否可以安全地忽略它们.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读