2016-01-21 29 views
1

JmsTests.java对理解构建代码的方式非常有帮助。代码是在https://github.com/spring-projects/spring-integration-java-dsl/blob/master/src/test/java/org/springframework/integration/dsl/test/jms/JmsTests.java是否有用于弹簧集成dsl错误处理的任何代码示例?

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

添加更多的上下文的问题:

  1. jmsMessageDrivenFlow:从传入队列并打印读取的有效载荷。如果有错误,然后将其发送到errorChannel()
  2. handleErrors():应该听errorChannel有送什么东西给了fatalErrorQueue

jmsMessageDrivenFlow()工作正常,并打印消息。我期待只有在jmsMessageDrivenFlow期间发生错误时才会调用错误处理程序。但是,errorhandler()也会被调用,并且会在致命队列中放入'Dispatcher failed to deliver Message'消息。

我希望在这种情况下甚至不应该调用错误通道,因为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 [[email protected]d91] (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 [[email protected]00b] (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} [email protected] 
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 = [email protected], 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}] 
+0

正如你所看到的家伙在这里不喜欢你的问题。你应该用一些关于这个问题的代码对它进行重新说明。并指出您希望看到错误处理的地方。 –

+0

thx回复。添加示例代码来解释示例的必要性 – StartingDev

+0

对不起,谁是'errorhandler()'?我没有看到你的配置 –

回答

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 -> ,这是单向停止流量的方式。

既然你真的有回复.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()上我们在AbstractMessageListenerContainer落得Jms.messageDriverChannelAdapter()

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); 

难道不是吗?

UPDATE

能否请您解释一下为什么messagingGateway发送有效载荷errorChannel()仅仅是因为我已经定义为非幸福路径scnenarios错误通道。

???即使使用XML定义,您也会得到相同的错误。 Java DSL在后台使用相同的组件。我不会解释普通的Java代码:你看到try...catch约在convertAndSend,你在运行时的条件定义了错误。这就是为什么你得到那个DestinationResolutionException。我们无法识别初始阶段的非欢乐路径,因为.handle()中的return只有在运行时才能幸运null。所以,从配置的角度来看,一切都很好。从其他方面来说,即使没有outputChannel,您仍然可以在request/reply情况下满意,当时我们有replyChannel标题。

+0

我可以终止使jmsMessageDrivenFlow()成功的句柄(message - >)。刚刚测试,并且工作。但是,如果明天,我想继续处理消息,而不是终止于System.out,那么我最终会遇到同样的问题。如果我将.errorChannel()添加到messageDriverChannelAdapter,为什么框架会变成messagingGateway的逻辑。我想我不明白添加errorChannel到消息适配器的影响。 – StartingDev

+1

那么,你可以尽可能多地继续流程,你应该明白它是“单向”的,你应该在某个地方终止它。有时它甚至足够从''.handle()'返回'null' –

+0

非常感谢。我认为快乐之流是单向流动是非常有意义的。而且,这正是我的目标。它让我感到困惑,因为我为错误条件添加了错误通道,即使jmsMessageDrivenFlow()中没有错误,handleErrors()流也会被调用。 IIRC在Spring集成XML流程中,仅在错误条件下调用错误通道。您能否解释为什么messagingGateway将有效载荷发送到errorChannel()是因为我已经为非欢乐路径scnenarios定义了错误频道。 – StartingDev