Error handling 关于Spring消息驱动通道适配器的查询

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

我正在使用Spring的消息驱动通道适配器。 我的组件正在使用来自Tibco主题的消息并发布到RabbitMQ主题

因此,消息流如下所示: Tibco->(订阅人)组件(发布至)->RabbitMQ

服务激活器如下所示:正如我们看到的,有一个输入通道和一个输出通道。BeanStoreandForwardActivator将具有业务逻辑(在方法createIssueFintereStorAtorRecord中)

i、 e.由于事务未提交-来自持久主题的同一消息被反复使用。我的目标是在使用消息后将ACK发送回代理(无论是否捕获异常)

明天我将尝试错误频道

问候
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" />