有没有用于弹簧集成dsl错误处理的代码示例?

时间:2016-01-21 23:05:41

标签: spring-integration

JmsTests.java非常有助于理解构造代码的方法。代码位于https://github.com/spring-projects/spring-integration-java-dsl/blob/master/src/test/java/org/springframework/integration/dsl/test/jms/JmsTests.java

但是,对于错误处理,我有点像我们一样搞清楚。是否有任何测试或参考代码显示构造错误通道或使用子流委派错误处理的好方法?

在问题中添加更多内容:

  1. jmsMessageDrivenFlow:从传入队列中读取并打印有效负载。如果有错误,则将其发送到errorChannel()
  2. handleErrors():应该监听errorChannel并将任何内容发送到fatalErrorQueue
  3. jmsMessageDrivenFlow()工作正常并打印消息。我希望只有在jmsMessageDrivenFlow期间出现错误时才会调用错误处理程序。但是,错误处理程序()也会被调用,并且它会使“调度程序”无法传递消息'致命队列中的消息。

    我希望在这种情况下甚至不应该调用错误通道,因为jmsMessageDrivenFlow()没有创建任何错误。显然,如果我在jmsMessageDrivenFlow()中省略了.errorChannel(errorChannel()),则不会调用错误流,只会按预期执行jmsMessageDrivenFlow()。

    @EnableIntegration
    @IntegrationComponentScan
    @Component
    @Configuration
    public class MessageReceiver {
        private static final Logger logger = LoggerFactory.getLogger(MessageReceiver.class);
        String fatalErrorQueue = "fatal";
        String incomingQueue = "incoming";
    
        @Autowired
        private JmsMessagingTemplate jmsMessagingTemplate;
    
        @Bean
        public Queue incomingQueue() {
            return new ActiveMQQueue(incomingQueue);
        }
    
        @Bean
        public MessageChannel errorChannel() {
            return new DirectChannel();
        }
    
        @Bean
        public IntegrationFlow handleErrors() {
            return IntegrationFlows
                    .from("errorChannel")
                    .handle((payload,headers) -> {
                        System.out.println("processing error: "+payload.toString());
                        return payload;
                    })
                    .handle(Jms.outboundAdapter(jmsMessagingTemplate.getConnectionFactory()).destination(fatalErrorQueue))
                    .get();
        }
    
        @Bean
        public IntegrationFlow jmsMessageDrivenFlow() {
            return IntegrationFlows
                    .from(
                            Jms.messageDriverChannelAdapter(jmsMessagingTemplate.getConnectionFactory())
                                    .destination(incomingQueue)
                                    .errorChannel(errorChannel())
                    )
                    .handle((payload,headers) ->{
                        System.out.println("processing payload: "+payload.toString());
                        return payload;
                    })
                    .get();
        }
    }
    

    执行记录:

    2016-01-22 10:18:20,531 DEBUG DefaultMessageListenerContainer-1 ServiceActivatingHandler.handleMessage - ServiceActivator for [org.springframework.integration.dsl.LambdaMessageProcessor@522d5d91] (org.springframework.integration.handler.ServiceActivatingHandler#1) received message: GenericMessage [payload=SAMPLE QUEUE MESSAGE, headers={jms_redelivered=false, jms_correlationId=, jms_type=, id=78d5456e-4442-0c2b-c545-870d2c177802, priority=0, jms_timestamp=1453479493323, jms_messageId=ID:crsvcdevlnx01.chec.local-47440-1453310266960-6:2:1:1:1, timestamp=1453479500531}]
    processing payload: SAMPLE QUEUE MESSAGE
    2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - preSend on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
    2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 ServiceActivatingHandler.handleMessage - ServiceActivator for [org.springframework.integration.dsl.LambdaMessageProcessor@5545b00b] (org.springframework.integration.handler.ServiceActivatingHandler#0) received message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
    processing error: org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
    2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - preSend on channel 'handleErrors.channel#0', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
    2016-01-22 10:18:20,535 DEBUG DefaultMessageListenerContainer-1 JmsSendingMessageHandler.handleMessage - org.springframework.integration.jms.JmsSendingMessageHandler#0 received message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
    2016-01-22 10:18:20,537 DEBUG DefaultMessageListenerContainer-1 DynamicJmsTemplate.execute - Executing callback on JMS Session: ActiveMQSession {id=ID:MACD13-60edd8d-49463-1453479492653-1:1:1,started=true} java.lang.Object@858db12
    2016-01-22 10:18:20,568 DEBUG DefaultMessageListenerContainer-1 DynamicJmsTemplate.doSend - Sending created message: ActiveMQObjectMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@559da78d, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {timestamp=1453479500535}, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false}
    2016-01-22 10:18:20,570 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - postSend (sent=true) on channel 'handleErrors.channel#0', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=f434348c-f659-1e88-2eba-3d467761ab47, timestamp=1453479500535}]
    2016-01-22 10:18:20,571 DEBUG DefaultMessageListenerContainer-1 DirectChannel.send - postSend (sent=true) on channel 'errorChannel', message: ErrorMessage [payload=org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available, headers={id=dc87f71d-a38c-4718-a2e9-2fba2a7c847c, timestamp=1453479500535}]
    

1 个答案:

答案 0 :(得分:1)

行。谢谢。调查......但是从高处看,一切都按预期运作:

  1. 您的jmsMessageDrivenFlow()是单向流
  2. 您在该流程结尾处有非结束.handle()

    .handle((payload,headers) ->{
                    System.out.println("processing payload: "+payload.toString());
                    return payload;
                })
    

    由于您返回任何内容,因此流程会在标头中output-channelreplyChannelErrorMessage说明了这一点。

  3. 我告诉我关于完全修复错误的方法。对于您的情况,您只需将.handle((payload,headers) ->更改为.handle(message ->即可 这是单向停止流动的单向方式。

  4. 由于您在回复.handle()之后确实存在下一个端点的问题,messagingGateway会对此做出正确反应:

            this.messagingTemplate.convertAndSend(requestChannel, object, this.historyWritingPostProcessor);
        }
        catch (Exception e) {
            MessageChannel errorChannel = getErrorChannel();
            if (errorChannel != null) {
                this.messagingTemplate.send(errorChannel, new ErrorMessage(e));
            }
    

    这就是为什么你的handleErrors()能够处理这个错误。

    errorChannel()上没有Jms.messageDriverChannelAdapter()我们最终在AbstractMessageListenerContainer

    protected void executeListener(Session session, Message message) {
        try {
            doExecuteListener(session, message);
        }
        catch (Throwable ex) {
            handleListenerException(ex);
        }
    }
    

    其默认ErrorHandler为... null,我们只看到:

    logger.warn("Execution of JMS message listener failed, and no ErrorHandler has been set.", ex);
    

    不是吗?

    <强>更新

      

    请问你解释为什么messagingGateway将有效负载发送到errorChannel()只是因为我已经为非happy-path scnenarios定义了一个错误通道。

    ???即使使用XML定义,您最终也会遇到相同的错误。 Java DSL在后台使用相同的组件。我不会解释常规Java代码:您在try...catch周围看到convertAndSend,并且您在运行时的条件定义了错误。这就是你得到DestinationResolutionException的原因。我们无法在初始阶段识别非幸福路径,因为return中的.handle()只能在运行时才能幸运null。所以,从配置的角度来看一切都还可以。即使没有outputChannel,从另一边开始,当我们在此问题上有request/reply标题时,您仍可以使用replyChannel情节感到满意。