Spring与Citrus集成:没有输出通道或replyChannel标头可用

时间:2016-05-16 11:38:58

标签: java spring spring-integration citrus-framework

我已经配置了一个测试,我首先发送" Req"从服务器到我的应用程序,然后使用" Rsp"响应服务器。我成功收到请求消息,但在尝试响应时出现以下错误:

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

请参阅下面的我的bean配置: 的柑桔-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");

基本上,我的目的是接收关于&#34; req&#34;的数据。通道,然后将字节转换为字符串到req_transformed通道,然后验证字符串是否等于&#34; Req&#34;。然后,我想发送一个&#34; Rsp&#34;字符串返回,它被转换为字节,然后作为回复放到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%工作。为什么它不适用于网关?

2 个答案:

答案 0 :(得分:1)

我不熟悉柑橘,但在使用网关时,响应必须包含请求中的某些标头 - 特别是此情况下的replyChannel标头 - 这就是网关如何知道答复所针对的请求(那里)可能是通过网关的许多并发请求。

您可以使用一对collaborating TCP inbound/outbound channel adapters而不是入站网关,但是您仍然需要通过将请求中的ip_connectionId标头传播到请求,告诉出站适配器回复的套接字。回复。

答案 1 :(得分: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");

请注意,请求和响应都使用相同的同步端点。