所以设置如下:
<tx:advice id="txAdvice2" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="Throwable" no-rollback-for="ListenerExecutionFailedException"/>
</tx:attributes>
</tx:advice>
<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter"
channel-transacted="true"
advice-chain="txAdvice2" />
<int:chain input-channel="input-channel" output-channel="output-channel">
<int:service-activator ref="h1Handler" method="handle" />
<int:service-activator ref="h2Handler" method="handle" />
<int:service-activator ref="h3Handler" method="handle" />
<int:splitter />
</int:chain>
<int-amqp:outbound-channel-adapter channel="output-channel" exchange-name="outputit" amqp-template="rabbitTemplate" />
如果在执行此线程期间(因为所有这些链amqpIN-process-amqpOUT shold在单个线程中执行)我抛出ListenerExecutionFailedException,dataSourceTransactionManager将执行提交,但是amqp也会重新排队消息,因为传播了异常。
在这种情况下,如何告诉兔子确认消息成功?
另外,我看到我必须在属性实际异常类中放入no-rollback-for,因为我的内部异常只存储在“cause”属性中,而RuleBasedTransactionAttribute没有检查它。
还有一件事,如果我像这样制作配置:
<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter"
channel-transacted="true"
transaction-manager="dataSourceTransactionManager"
transaction-attribute="transactionAttribute" />
根本不考虑作为RuleBasedTransactionAttribute的transactionAttribute,即使我没有正确设置了回滚,也始终回滚dataSourceTransactionManager。
谢谢!
答案 0 :(得分:2)
您可以将自定义ErrorHandler
添加到侦听器容器(您必须在外部配置容器并在中提供引用)。container
属性
默认错误处理程序是ConditionalRejectingErrorHandler
,DefaultExceptionStrategy
将某些LEFE原因异常视为致命错误:
private boolean isCauseFatal(Throwable cause) {
return cause instanceof MessageConversionException
|| cause instanceof org.springframework.messaging.converter.MessageConversionException
|| cause instanceof MethodArgumentNotValidException
|| cause instanceof MethodArgumentTypeMismatchException
|| cause instanceof NoSuchMethodException
|| cause instanceof ClassCastException
|| isUserCauseFatal(cause);
}
从版本1.6.4开始,您可以继承默认DefaultExceptionStrategy
并将您的原因添加到isUserCauseFatal()
。
在1.6.4之前,您必须提供自己的FatalExceptionStrategy
(或错误处理程序实现)。
对于致命原因,处理程序抛出AmqpRejectAndDontRequeueException
,告诉容器nack(而不是重新排队)消息。
修改强>
顺便说一下,你不需要包装异常,容器会为你做那个......
protected Exception wrapToListenerExecutionFailedExceptionIfNeeded(Exception e, Message message) {
if (!(e instanceof ListenerExecutionFailedException)) {
// Wrap exception to ListenerExecutionFailedException.
return new ListenerExecutionFailedException("Listener threw exception", e, message);
}
return e;
}
<强> EDIT2 强>
我的错误,可以使用ErrorHandler
属性指定error-handler
。
<强> EDIT3 强>
或者,只需抛出一个AmqpRejectAndDontRequeueException
(将包含在LEFE
中)。