虽然异常在ErrorHandler

时间:2017-08-04 09:34:32

标签: spring spring-integration spring-transactions atomikos

我使用Spring集成JTA支持,通过Atomikos和JMS绑定到不同的Webshpere MQ和Oracle数据库。
对于其他人而言,它似乎与Spring Integration JMS with JTA rollback when message goes to errorChannel中的线程相同,但它根本不是 流程如下:

  • message-driven-channel-adapter接收事务
  • 中的消息
  • 一些转变
  • 具有更深层业务逻辑的ServiceActivator
  • 数据库更新

对于一个szenario来说,一切都很顺利: 如果在ServiceActivator中发生未经检查的异常(可能是由于不应该使用墨迹的数据),则会在ErrorHandler(通过ErrorChannel)中重新抛出并处理该消息。 在某些情况下,应该将orgininal传入消息发送到DeadLetter队列(Webshere MQ)。这是通过出站通道适配器完成的。

参见随附配置:

       <jms:message-driven-channel-adapter id="midxMessageDrivenAdapter"
                                            channel="midxReplyChannel"
                                            acknowledge="auto"
                                            transaction-manager="transactionManager"
                                            connection-factory="connectionFactory"
                                            concurrent-consumers="1"
                                            error-channel="errorChannel"
                                            max-concurrent-consumers="${cmab.integration.midx.max.consumer}"
                                            idle-task-execution-limit="${cmab.integration.midx.idleTaskExecutionLimit}"
                                            receive-timeout="${cmab.integration.midx.receiveTimeout}"
                                            destination="midxReplyQueue"/>
................
<int:service-activator input-channel="midxReplyProcessChannel" ref="processMidxReplyDbWriter" />

        <int:service-activator input-channel="errorChannel" ref="inputErrorHandler" />

        <jms:outbound-channel-adapter id="deadLetterOutboundChannelAdapter"
                                      channel="errorDlChannel" destination="deadLetterQueue"
                                      delivery-persistent="true" connection-factory="nonXAConnectionFactory"/>

一些重要提示:
消息驱动沟道适配器:

  • connectionFactory是一个与AtomikosConnectionFactoryBean相关的MQXAQueueConnectionFactory
  • transaction-manager是Spring JtaTransactionManager

出站信道适配器:
connection-factory是一个非XAConnectionFactory。

CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
.....
cachingConnectionFactory.setTargetConnectionFactory(mqQueueConnectionFactory);
return cachingConnectionFactory;

现在我发现了错误:
虽然我在ErrorHandler中处理了未经检查的异常(ref =“inputErrorHandler”;将消息发送到DeadLetter-Queue),但启动了回滚,消息驱动通道适配器一次又一次地收到消息。
实际上,消息是通过出站通道适配器传递给DeadLetterQueue的事实。目的地(deadLetterQueue)包含失败的消息
问题:我做错了什么?尽管我在ErrorHandler中处理了异常,但是回滚失败的原始传入消息 任何帮助真的很感激。非常感谢提前。

1 个答案:

答案 0 :(得分:0)

关于我的评论,请参阅我的InputErrorHandler的代码:

if (throwable instanceof MessageHandlingException) {

            MessageHandlingException messageHandlingException = (MessageHandlingException) throwable;

            if (messageHandlingException.getCause() != null
                    && (messageHandlingException.getCause() instanceof CmabProcessDbException
                    || messageHandlingException.getCause() instanceof CmabReplyFormatException)) {

                String appMessage = ((CmabException) messageHandlingException.getCause()).getAppMessagesAsString();

                LOGGER.error(String.format("cmab rollback exception occured: %s", appMessage));
                LOGGER.error("******** initiate rollback *********");

                throw throwable.getCause();

            } else {

                ErrorDto payload = fillMessagePayload(messageHandlingException, throwableClassName);
                sendMessageToTargetQueue(payload);
            }

正如我所提到的,“business”ServiceActivator会抛出一个未经检查的异常,因此在这种情况下,ELSE-Statements正在调用。 在其中我用MessagBuilder建立一个Message并将它发送到errorDlChannel(s。在出站通道适配器之上!)。

 private void sendMessageToDeadLetterQueue(Message<?> message, String description, String cause) {

.......

        Message<?> mb =
                MessageBuilder.withPayload(message.getPayload())
                        .copyHeaders(message.getHeaders())
                        .setHeaderIfAbsent("senderObject", this.getClass().getName())
                        .setHeaderIfAbsent("errorText", description)
                        .setHeaderIfAbsent("errorCause", errorCause).build();

        errorDlChannel.send(mb);

    }

这就是全部。对于这种情况,这是最后一个陈述。我的ErrorHandler的main方法中没有任何其他内容。没有重新抛出或其他东西。
所以这就是我困惑的原因。对我来说,异常是通过将它发送到errorDlChannel(outbound-channel-adapter - &gt; DeadLetterQueue)来处理的。
我在DeadLetter Queue上看到了这条消息,但仍然发生了jta回滚......而IMO这不应该是蜜蜂。