2016-05-16 45 views
1

我配置了一個測試,首先將「請求」從服務器發送到我的應用程序,然後用「Rsp」響應服務器。我成功地接收到請求消息,但隨後在嘗試響應時,出現以下錯誤:春季與Citrus集成:沒有輸出通道或回覆通道頭可用

org.springframework.messaging.MessagingException: Dispatcher failed to deliver Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available 
at org.springframework.integration.dispatcher.AbstractDispatcher.wrapExceptionIfNecessary(AbstractDispatcher.java:133) 
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:120) 
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147) 
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120) 
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) 
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442) 
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392) 
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) 
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) 
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) 
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:231) 
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:154) 
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:102) 
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:105) 
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) 
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) 
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147) 
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120) 
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) 
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442) 
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392) 
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) 
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) 
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) 
at com.consol.citrus.channel.ChannelProducer.send(ChannelProducer.java:66) 
at com.consol.citrus.actions.SendMessageAction.doExecute(SendMessageAction.java:103) 
at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42) 
at com.consol.citrus.TestCase.executeAction(TestCase.java:211) 
... 31 more 
Caused by: org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available 
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:226) 
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:154) 
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:102) 
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:105) 
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) 
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) 
... 57 more 

請參考下面我的豆配置: 柑橘-config.xml中

<citrus:channel-endpoint id="citrusServiceReqEndpoint" 
         channel-name="req_transformed" /> 

<citrus:channel-endpoint id="citrusServiceRspEndpoint" 
         channel-name="rsp" /> 


<int-ip:tcp-connection-factory id="client" 
           type="client" host="localhost" port="12345" single-use="false" 
           so-timeout="10000" using-nio="true" deserializer="javaSerializer" 
           serializer="javaSerializer" /> 

<bean id="javaSerializer" 
     class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer" /> 

<int:channel id="req" /> 

<int:channel id="req_transformed"> 
    <int:queue /> 
</int:channel> 

<int:channel id="rsp"> 
</int:channel> 

<int:channel id="rsp_transformed"> 
</int:channel> 

<int:object-to-string-transformer id="incomingTransformer" input-channel="req" output-channel="req_transformed" /> 

<int:object-to-string-transformer id="outgoingTransformer" input-channel="rsp" output-channel="rsp_transformed" /> 

<int-ip:tcp-inbound-gateway id="gateway" 
          connection-factory="client" 
          request-channel="req" 
          reply-channel="rsp_transformed" 
          client-mode="true" /> 

測試用例:

receive("citrusServiceReqEndpoint").messageType(MessageType.PLAINTEXT).payload("Req"); 
     send("citrusServiceRspEndpoint").payload("Rsp"); 
     receive("citrusServiceReqEndpoint").messageType(MessageType.PLAINTEXT).payload("Req2"); 
     send("citrusServiceRspEndpoint").payload("Rsp2"); 

基本上,我的意圖是接收「請求」通道上的數據,然後將字節轉換爲字符串到req_transformed通道,然後驗證字符串是否等於「請求」。然後,我想發送一個「Rsp」字符串,它被轉換爲字節,然後作爲回覆放到rsp_transformed通道中。

請幫我理解問題所在。請注意,當我用兩個通道適配器替換tcp-inbound-gateway時:

<int-ip:tcp-outbound-channel-adapter 
      id="outboundClient" channel="rsp" connection-factory="client" /> 

<int-ip:tcp-inbound-channel-adapter 
      id="inboundClient" channel="req" connection-factory="client" client-mode="true" /> 

測試用例工作100%。那麼爲什麼它不適用於網關?

回答

1

您的tcp-inbound-gateway使用同步消息傳遞。因此,您需要在Citrus中使用同步通道端點。

<citrus:channel-sync-endpoint id="citrusServiceSyncEndpoint" 
        channel-name="req_transformed"/> 

同步端點將照顧特殊的標題,使req/resp通道與請求/回覆相關聯。所以,你的測試看起來像這樣:

receive("citrusServiceSyncEndpoint") 
    .messageType(MessageType.PLAINTEXT) 
    .payload("Req"); 
send("citrusServiceSyncEndpoint") 
    .messageType(MessageType.PLAINTEXT) 
    .payload("Rsp"); 

請注意,同樣的同步端點用於請求和響應。

+0

哇兩個作者的各自框架回復我的問題,並幫助我解決它!非常感謝你的先生:) – mdewit

1

我對柑橘不熟悉,但是在使用網關時,響應必須包含某些來自請求的頭部 - 特別是本例中的replyChannel頭部 - 這就是網關如何知道回覆是哪個請求的(可能有很多通過網關的併發請求)。

你可以用一對collaborating TCP inbound/outbound channel adapters代替入站網關,但那麼你仍然需要告訴哪個插座的答覆是,從請求到答覆傳播ip_connectionId頭出站適配器。

+0

好的,謝謝我認爲這會對我有所幫助。我可能必須在管道中放置一些組件,然後纔會存儲接收到的頭文件,然後在發送後使用此值填充響應。 – mdewit