我使用Spring集成JTA支持,通过Atomikos和JMS绑定到不同的Webshpere MQ和Oracle数据库。
对于其他人而言,它似乎与Spring Integration JMS with JTA rollback when message goes to errorChannel中的线程相同,但它根本不是
流程如下:
对于一个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"/>
一些重要提示:
消息驱动沟道适配器:
出站信道适配器:
connection-factory是一个非XAConnectionFactory。
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
.....
cachingConnectionFactory.setTargetConnectionFactory(mqQueueConnectionFactory);
return cachingConnectionFactory;
现在我发现了错误:
虽然我在ErrorHandler中处理了未经检查的异常(ref =“inputErrorHandler”;将消息发送到DeadLetter-Queue),但启动了回滚,消息驱动通道适配器一次又一次地收到消息。
实际上,消息是通过出站通道适配器传递给DeadLetterQueue的事实。目的地(deadLetterQueue)包含失败的消息
问题:我做错了什么?尽管我在ErrorHandler中处理了异常,但是回滚失败的原始传入消息
任何帮助真的很感激。非常感谢提前。
答案 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这不应该是蜜蜂。