Error handling 关于Spring消息驱动通道适配器的查询
我正在使用Spring的消息驱动通道适配器。 我的组件正在使用来自Tibco主题的消息并发布到RabbitMQ主题 因此,消息流如下所示: Tibco->(订阅人)组件(发布至)->RabbitMQ 服务激活器如下所示:正如我们看到的,有一个输入通道和一个输出通道。BeanStoreandForwardActivator将具有业务逻辑(在方法createIssueFintereStorAtorRecord中) i、 e.由于事务未提交-来自持久主题的同一消息被反复使用。我的目标是在使用消息后将ACK发送回代理(无论是否捕获异常) 明天我将尝试错误频道 问候Error handling 关于Spring消息驱动通道适配器的查询,error-handling,spring-jms,message-listener,durable-subscription,Error Handling,Spring Jms,Message Listener,Durable Subscription,我正在使用Spring的消息驱动通道适配器。 我的组件正在使用来自Tibco主题的消息并发布到RabbitMQ主题 因此,消息流如下所示: Tibco->(订阅人)组件(发布至)->RabbitMQ 服务激活器如下所示:正如我们看到的,有一个输入通道和一个输出通道。BeanStoreandForwardActivator将具有业务逻辑(在方法createIssueFintereStorAtorRecord中) i、 e.由于事务未提交-来自持久主题的同一消息被反复使用。我的目标是在使用消息后将A
D向消息驱动适配器添加一个
错误通道
;ErrorMessage
将包含一个包含两个字段的MessaginException
有效载荷;原因
(异常)和失败消息
如果使用默认的error channel=“errorChannel”
,则会记录异常
如果您想做更多的事情,您可以配置自己的错误通道,并向其中添加一些流
编辑:
关于你在下面的评论
有效负载不能为null
不是堆栈跟踪;这是一条信息
这就是说,负载不能为空
看起来像一条Spring集成消息;它可能在消息转换期间被抛出到消息侦听器适配器中,这是在我们到达故障可以进入错误通道的点之前;这样的异常将被抛出回容器
启用调试日志记录并查找此日志项:
logger.debug("converted JMS Message [" + jmsMessage + "] to integration Message payload [" + result + "]");
另外,提供完整的堆栈跟踪
编辑#2
因此,我通过在自定义的MessageConverter
中强制将转换后的有效负载设置为null,重现了您的问题
回滚事务后,容器将调用DMLC错误处理程序,因此无法停止回滚
我们可以向适配器添加一个选项,以不同方式处理此类错误,但这需要一些工作
同时,一个解决办法是编写一个定制的消息转换器
;有点像里面的那个
然后,您的服务将必须处理“收到的坏消息”负载
然后提供如下自定义转换器
<jms:message-driven-channel-adapter id="jmsIn"
destination="requestQueue" acknowledge="transacted"
message-converter="converter"
channel="jmsInChannel" />
<beans:bean id="converter" class="foo.MyMessageConverter" />
Hi Gary,我注意到格式错误消息的异常在容器部分中被捕获,即bean id=“oratorIssueOfInterestmessageListenerContainer”。这就是我尝试添加自定义错误处理程序的原因(如上所示)。但异常似乎被“优雅地”捕获,但事务没有提交,即没有向代理发送ack,因为它是一个持久的主题-相同的消息被反复使用并循环。处理异常并将ACK发送回代理的最佳方法是什么?您需要显示堆栈跟踪;包含HashMap的ObjectMessage不应“格式错误”。您不应该使用ErrorHandler
来处理MessageHandlingException
;如我所说,此类异常应该在错误通道中处理。你是对的!HashMap是个骗局。我放在MessageListenerContainer下的错误处理程序显示以下stacktrace:负载不能为null。因此,我似乎得到了一个负载为空的JMS-因为我使用了以下消息选择器:-负载为null/空-MessageListenerContainer中抛出了一个异常(并被errorHandler捕获)-我认为这就是发生的情况。我引入了一个错误通道=“errorChannel”在“消息驱动通道适配器”下,但由于容器本身中捕获了异常,因此根本不会调用错误通道!我需要找到一种方法,即使有一个空的有效负载,也要确认经纪人。嗨,加里,请查看此链接:我想知道Tibco是否也有同样的情况?我看到了类似的行为,即消息没有有效负载(IBM MQ头:content=nil)� JMS侦听器抛出一个异常,该异常不会传递到errorchannel,而是回滚事务,将消息留在队列上(用于立即和无限重试)。-消息的有效负载为空� JMS侦听器或SI Base Transformer会抛出一个异常,该异常不会传递到错误通道。
<bean id="oratorIssueOfInterestmessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="oratorIssueOfInterestTibcoConnectionFactory" />
<property name="destination" ref="oratorTibcojmsDestination" />
<property name="sessionTransacted" value="true" />
<property name="maxConcurrentConsumers" value="1" />
<property name="concurrentConsumers" value="1" />
<property name="receiveTimeout" value="5000" />
<property name="recoveryInterval" value="60000" />
<property name="autoStartup" value="true" />
<property name="exposeListenerSession" value="false" />
<property name="subscriptionDurable" value="true" />
<property name="durableSubscriptionName" value="${topic.orator.durable-subscription-name}" />
<property name="messageSelector" value="${topic.orator.selector}" />
</bean>
<bean id="oratorIssueOfInterestmessageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="oratorIssueOfInterestTibcoConnectionFactory" />
<property name="destination" ref="oratorTibcojmsDestination" />
<property name="sessionTransacted" value="true" />
<property name="maxConcurrentConsumers" value="1" />
<property name="concurrentConsumers" value="1" />
<property name="receiveTimeout" value="5000" />
<property name="recoveryInterval" value="60000" />
<property name="autoStartup" value="true" />
<property name="exposeListenerSession" value="false" />
<property name="subscriptionDurable" value="true" />
<property name="durableSubscriptionName" value="${topic.orator.durable-subscription-name}" />
<property name="messageSelector" value="${topic.orator.selector}" />
<property name="errorHandler" ref="myErrorHandler"/>
</bean>
<bean id="myErrorHandler"
class="com.igate.firds.icmf.activators.concentrator.MyErrorHandler" />
@Service
public class MyErrorHandler implements ErrorHandler{
private static Log log = LogFactory.getLog(MyErrorHandler.class);
@Override
public void handleError(Throwable t) {
if (t instanceof MessageHandlingException) {
MessageHandlingException exception = (MessageHandlingException) t;
if (exception != null) {
org.springframework.messaging.Message<?> message = exception.getFailedMessage();
Object payloadObject = message.getPayload();
if (null != payloadObject) {
log.info("Payload is not null, type is: " + payloadObject.getClass());
}
}
} else {
log.info("Exception is not of type: MessageHandlingException ");
}
}
Exception is not of type: MessageHandlingException
Exception is not of type: MessageHandlingException
Exception is not of type: MessageHandlingException
logger.debug("converted JMS Message [" + jmsMessage + "] to integration Message payload [" + result + "]");
<jms:message-driven-channel-adapter id="jmsIn"
destination="requestQueue" acknowledge="transacted"
message-converter="converter"
channel="jmsInChannel" />
<beans:bean id="converter" class="foo.MyMessageConverter" />