@MessageDriven 事务和重新传递语义

Posted

技术标签:

【中文标题】@MessageDriven 事务和重新传递语义【英文标题】:@MessageDriven transactions and redelivery semantics 【发布时间】:2012-01-31 03:37:01 【问题描述】:

完成以下任务的最佳方法是什么?

@MessageDriven bean 在数据库上做了一些工作 失败时,我想回滚数据库事务 但我也希望不要重新传递 JMS 消息,即不要重试。

我能想到一些可能起作用的方法。还有其他的吗,哪个最好?

使用@TransactionManagement(type=BEAN)UserTransaction,捕获异常后显式回滚。例如:

catch (Exception e) e.printStackTrace(); utx.rollback();

使用容器管理的事务,在onMessage 上指定@TransactionAttribute(value=NOT_SUPPORTED),然后使用@TransactionAttribute(value=REQUIRED) 将数据库活动委托给单独的方法。

不理会事务处理并重新配置服务器中的重试属性。我正在使用 Glassfish 3.1.1,但我不确定如何设置它。

不理会所有内容,并在 onMessage 正文中明确检查消息是否重新发送,如果重新发送则退出。 (message.getJMSRedelivered()?)

那里有什么效果很好?是否有处理此问题的标准/最佳实践方法?

【问题讨论】:

【参考方案1】:

最简单和最便携的方法是在您声明的onMessage() 上使用@TransactionAttribute(value=NOT_SUPPORTED),并使用@TransactionAttribute(REQUIRES_NEW) 将数据库工作移动到另一个bean

注意单独的方法方法,因为这不起作用。在 JMS MDB 中,onMessage() 方法是唯一可以使用@TransactionAttribute 的方法。

【讨论】:

谢谢,这很好用。 MDB 中关于@TransactionAttribute 的注释很关键——你是对的,你只能注释onMessage。最后我没有注释onMessage,但确实使用REQUIRES_NEW将逻辑移动到另一个EJB。 作为注释,它适用于带有“REQUIRED”注释的子 EJB。【参考方案2】:

就我个人而言,我从未在 MDB 中做任何工作,而是立即分派给(注入的)会话 bean。

然后这个 bean 执行 DB 工作。它要么启动一个新事务,要么我从 bean 中捕获任何异常并将其记录下来(但不要让它传播,因此不会重新传递)。

这还有一个好处是业务逻辑很容易从其他地方重用。

【讨论】:

以上是关于@MessageDriven 事务和重新传递语义的主要内容,如果未能解决你的问题,请参考以下文章

「首席看Kafka」Apache Kafka中的事务

kafkaKafka 幂等 Producer

kafkaApache Kafka 中的事务

62Spark Streaming:容错机制以及事务语义

在@MessageDriven bean 中使用 amazon sqs - 池化/并行处理

ActriveMQ-消息重新传递和死信队列(DLQ)处理