在TransactionRolledBackException上使用ErrorHandler的Tibco + Spring JMS行为

时间:2014-07-03 03:15:18

标签: jms spring-jms tibco

我想澄清通过Spring(4.1)JMS配置使用的Tibco总线(6.1)的行为 - 指定和不指定ErrorHandler,以及TransactionRolledBackException的特定情况。

我使用“事务处理”模式配置JMS侦听器,如下所示:

<jms:listener-container connection-factory="singleConnectionFactory"                 
     acknowledge="transacted" task-executor="myTaskExecutor" concurrency="${my.queue.concurrency}">
     <jms:listener destination="${queue.destination}" ref="myProcessor" method="processMyMessage" />
</jms:listener-container>

并将队列的'maxRedelivery'设置为2。

以下是在myProcessor.processMyMessage()中处理事件的场景:

  1. 消息处理成功;结果:消息已确认并从队列中删除
  2. 通过业务逻辑或Spring容器(比如OOM或HectorException)抛出运行时异常;结果:消息未确认,重新放回总线并重新传送最多2次
  3. 抛出
  4. org.springframework.jms.TransactionRolledBackException(由Spring假设) - 因为它是一个运行时异常,结果行为与2中的相同。(这是正确的吗?)
  5. 现在,我正在添加一个显式的ErrorHandler来更好地记录一些运行时异常:

    <jms:listener-container connection-factory="singleConnectionFactory"                 
         acknowledge="transacted" task-executor="myTaskExecutor" concurrency="${my.queue.concurrency}"
    error-handler="myErrorHandler">
         <jms:listener destination="${queue.destination}" ref="myProcessor" method="processMyMessage" />
    </jms:listener-container>
    

    以下是ErrorHandler的实现,我们吞下TransactionRolledBackException:

    import org.springframework.jms.TransactionRolledBackException;
    import org.springframework.util.ErrorHandler;
    public class JMSListenerErrorHandler implements ErrorHandler {
        @Override
        public void handleError(Throwable t) {
            if (t.getCause() instanceof TransactionRolledBackException) {
                log.warn("JMS transaction rollback; reason: " + t.getMessage(), t);
            } else {
                log.error(t.getMessage(), t);
                throw new RuntimeException(t);
            }
        }
    

    每个用例会发生什么?这是我的猜测:

    1. 无变化
    2. 没有变化 - 重新抛出此运行时异常,因此消息将不会被确认,并且将被重新传送最多2次
    3. TransactionRolledBackException:当我在ErrorHandler中处理此异常时 - 这是在TX已经回滚之后发生的(正如名称RolledBack建议的那样)并且消息被标记为未确认,因此导致它被重新传递为情况2.?或者我是否通过吞下这个例外来有效地导致此消息被确认?
    4. 还有更多问题:

      • 在什么条件下Spring会抛出一个org.springframework.jms.TransactionRolledBackException?
      • 是否处理了与任何其他运行时异常不同的TransactionRolledBackException?

      谢谢,

      码头

1 个答案:

答案 0 :(得分:1)

当底层JMS客户端抛出javax.jms.TransactionRolledBackException时,Spring JMS仅抛出该异常 - 它只是一个未经检查的包装器异常 - 请参阅JmxUtils.convertJmsAccessException()

查看堆栈跟踪,您将看到它被抛出的位置/原因。

一般情况下,即如果它被丢弃在容器的会话中,捕获它就不会产生任何影响 - 该事务已经回滚;但堆栈跟踪是关键。