Spring Integration Exception忽略int-jms上的容器设置:message-driven-channel-adapter

时间:2014-03-16 04:30:08

标签: spring-integration

根据我的理解,ServiceActivator中的运行时异常应该向errorChannel发送消息。

但是如果没有设置errorHandler,那么这不起作用。我甚至试图设置errorHandler

 <bean id="translatorContainer"    class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory" />
        <property name="errorHandler" ref="myErrorHandler"/>
        <property name="destination" ref="TRANSLATED-MDCAD" />
        <property name="sessionTransacted" value="true" />
        <property name="maxConcurrentConsumers" value="50" />
        <property name="concurrentConsumers" value="1" />
        <property name="receiveTimeout" value="5000" />
        <property name="recoveryInterval" value="60000" />
        <property name="autoStartup" value="false" />
    </bean>

<int:channel id="TRANSLATED-MSG-CHANNEL"/>

<bean id="TRANSLATED-MDCAD" class="com.ibm.mq.jms.MQQueue">
    <constructor-arg value="TRANSLATED-MESSAGE-QUEUE" />
</bean>

<int-jms:message-driven-channel-adapter
    id="MDB-TRANSLATED" 
    channel="TRANSLATED-MSG-CHANNEL" container="translatorContainer" acknowledge="transacted"/>


<int:service-activator input-channel="IN-MSG-CHANNEL"
    output-channel="TRANSLATED-MSG-CHANNEL" ref="myProcess"
    method="execute" /> 

但是在myProcess(ServiceActivator)中的RuntimeException上,我在日志中看到了以下内容

WARN : [2014-03-16 00:11:51.219] org.springframework.jms.listener.DefaultMessageListenerContainer - Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.integration.MessagingException: failed to handle incoming JMS Message
    at org.springframework.integration.jms.SubscribableJmsChannel$DispatchingMessageListener.onMessage(SubscribableJmsChannel.java:164)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:561)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:499)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1059)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1051)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:948)
    at java.lang.Thread.run(Thread.java:662)

我调试了DefaultMessageListenerContainer,JmsMessageDrivenEndpointParser和其他一些内部类,发现容器设置正确。

但是当抛出异常时,它使用默认容器(不是我在int-jms上设置的那个:message-driven-channel-adapter:translatorContainer,它设置了errorHandler)

可能是什么原因?是否有任何其他备用设置我可以尝试将运行时异常重定向到errorChannel?如果您需要更多信息,请告诉我

我使用的是Spring集成版本2.2.5

#### DETAIL CONFIG
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
        ">


    <bean id="connectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
        <property name="hostName">
            <value>${mq_hostname}</value>
        </property>
        <property name="port">
            <value>${mq_port}</value>
        </property>
        <property name="queueManager">
            <value>${mq_queuemanager}</value>
        </property>
        <property name="channel">
            <value>${mq_channel}</value>
        </property> 
        <property name="transportType" value="1" />
        <property name="useConnectionPooling">
            <value>true</value>
        </property>
    </bean>




    <int:annotation-config />

    <int:message-history />


    <bean id="defaultMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="destination" ref="DEBATCHED-MDCAD" />
            <property name="connectionFactory" ref="connectionFactory" />
    <property name="errorHandler" ref="manifestErrorHandler"/>
     <property name="sessionTransacted" value="true" />
    <property name="maxConcurrentConsumers" value="50" />
    <property name="concurrentConsumers" value="1" />
    <property name="receiveTimeout" value="5000" />
    <property name="recoveryInterval" value="60000" />
    <property name="autoStartup" value="false" />
</bean>
    </bean>

    <bean id="translatorContainer"  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="destination" ref="TRANSLATED-MDCAD" />
            <property name="connectionFactory" ref="connectionFactory" />
    <property name="errorHandler" ref="manifestErrorHandler"/>
    <property name="sessionTransacted" value="true" />
    <property name="maxConcurrentConsumers" value="50" />
    <property name="concurrentConsumers" value="1" />
    <property name="receiveTimeout" value="5000" />
    <property name="recoveryInterval" value="60000" />
    <property name="autoStartup" value="false" />
</bean>
    </bean>




    <!-- Global Channel Interceptor -->
    <int:channel-interceptor ref="metadataInterceptor"
        pattern="*CHANNEL" order="1" />

    <int:wire-tap pattern="*CHANNEL" order="1" channel="logger" />



    <int:gateway id="manifestGateway"
        service-interface="gov.dhs.cbp.manifest.oceanexport.gateway.ManifestGateway" error-channel="ERRORS-MSG-CHANNEL" /> 

    <int:logging-channel-adapter id="logger"
        level="ERROR" log-full-message="true" />

    <int-jms:channel id="INBOUND-MSG-CHANNEL" queue-name="INBOUND"  error-handler="manifestErrorHandler"/>



    <int:channel id="DEBATCHED-MSG-CHANNEL" />

    <bean id="DEBATCHED-MDCAD" class="com.ibm.mq.jms.MQQueue">
        <constructor-arg value="DEBATCHED" />
    </bean>



    <int-jms:message-driven-channel-adapter
        id="MDB-DEBATCHED" 
        channel="DEBATCHED-MSG-CHANNEL" container="defaultMessageListenerContainer" acknowledge="transacted"/>

    <bean id="manifestErrorHandler" class="gov.dhs.cbp.manifest.process.util.ManifestErrorHandler"/>



        <int:channel id="TRANSLATED-MSG-CHANNEL"/>

    <bean id="TRANSLATED-MDCAD" class="com.ibm.mq.jms.MQQueue">
        <constructor-arg value="TRANSLATED" />
    </bean>


    <int-jms:message-driven-channel-adapter
        id="MDB-TRANSLATED" 
        channel="TRANSLATED-MSG-CHANNEL" container="translatorContainer" acknowledge="transacted"/>


    <int:channel id="ERRORS-MSG-CHANNEL" />

    <bean id="ERROR-EXTERNAL" class="com.ibm.mq.jms.MQQueue">
        <constructor-arg value="ERRORS" />
    </bean>


    <int-jms:outbound-channel-adapter id="ERROR-EXTERNAL-ADAPTER"
        channel="ERRORS-MSG-CHANNEL" destination="ERROR-EXTERNAL" />



    <int-jms:outbound-channel-adapter id="ERROR-CHANNEL-EXTERNAL-ADAPTER"
        channel="errorChannel" destination="ERROR-EXTERNAL" />





    <!-- ## Service Activator ## -->
    <int:service-activator input-channel="DEBATCHED-MSG-CHANNEL"
        output-channel="TRANSLATED-MSG-CHANNEL" ref="manifestProcess"
        method="execute" /> 


    <!--  DEBATCHER - SPLITTER -->
    <int:splitter input-channel="INBOUND-MSG-CHANNEL"
        output-channel="DEBATCHED-MSG-CHANNEL" ref="debatcherService"
        method="execute" />



    <!-- RESPONSE SERVICE / NOT ROUTER DUE TO BUSINESS LOGIC -->
    <int:service-activator input-channel="TRANSLATED-MSG-CHANNEL" ref="responseService"
        method="generateResponse"/>

    <bean id="pool"
        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="8" />
    </bean>

<!--
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
    <property name="retryPolicy">
        <bean class="org.springframework.retry.policy.SimpleRetryPolicy">
            <property name="maxAttempts" value="4" />
        </bean>
    </property>
    <property name="backOffPolicy">
        <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" <value="1000" />
            <property name="multiplier" value="5" />
        </bean>
    </property>
</bean>
-->

</beans>

使用RETRY模板解决问题

<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
    <property name="retryPolicy">
        <bean class="org.springframework.retry.policy.SimpleRetryPolicy">
            <property name="maxAttempts" value="1" />
        </bean>
    </property>
    <property name="backOffPolicy">
        <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
            <property name="initialInterval" value="1000" />
            <property name="multiplier" value="5" />
        </bean>
    </property>
</bean>


    <int:service-activator input-channel="DEBATCHED-MSG-CHANNEL"
        output-channel="TRANSLATED-MSG-CHANNEL" ref="manifestProcess"
        method="execute" >  
         <int:request-handler-advice-chain>
        <bean class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
            <property name="recoveryCallback">
                <bean class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
                    <constructor-arg ref="errorChannel" />
                </bean>
            </property>
            <property name="retryTemplate" ref="retryTemplate" />
        </bean>
    </int:request-handler-advice-chain>
    </int:service-activator>

1 个答案:

答案 0 :(得分:2)

正如我们在StackTrace中看到的那样,问题出在SubscribableJmsChannel<int-jms:channel id="fooChannel" queue-name="foo"/>),您不使用自定义container

但是您显示了<int-jms:message-driven-channel-adapter>的配置。

所以,小心分析问题。

现在,如果您希望<int-jms:channel/>采用相同的行为,则可以将myErrorHandler注入频道的媒体资源error-handler