我正处于请求/回复场景,我收到了需要通过相同输入连接回复的请求。为了给出响应,我需要向另一个系统做一个websocket请求。现在我正在通过这种方式将输出通道连接到网关的回复通道(我正在使用变换器来调整传入的消息):
<int:channel id="emrOutboundMessageTransformedChannel"/>
<int:channel id="emrInboundMessageTransformerChannel"/>
<int:channel id="emrOutboundChannel"/>
<int:channel id="cloudOutboundChannel"/>
<!-- Server WebSocket -->
<beans:bean id="webSocketClient"
class="org.springframework.web.socket.client.standard.StandardWebSocketClient"/>
<int-websocket:client-container id="webSocketClientContainer"
client="webSocketClient"
uri="ws://${cloud.webSocket.host}:${cloud.webSocket.port}"/>
<!-- Client Inbound -->
<int:gateway id="emrInboundGateway"
service-interface="com.roche.iconnect.emr.core.EmrMessageInjector">
<int:method name="injectMessage" request-channel="emrInboundMessageTransformerChannel" reply-channel="emrOutboundMessageTransformedChannel"/>
</int:gateway>
<int:transformer
id="emrInboundTransformer"
input-channel="emrInboundMessageTransformerChannel"
output-channel="cloudOutboundChannel"
method="convertEmrMessageToGenericMessage">
<beans:bean class="com.roche.iconnect.emr.EmrMessageAdapter"/>
</int:transformer>
<!-- Client Outbound -->
<int:transformer
id="emrOutboundTransformer"
input-channel="emrOutboundChannel"
output-channel="emrOutboundMessageTransformedChannel"
method="convertGenericMessageToEmrMessage">
<beans:bean class="com.roche.iconnect.emr.EmrMessageAdapter"/>
</int:transformer>
<!-- Server Inbound -->
<int-websocket:inbound-channel-adapter id="webSocketClientInboundAdapter"
container="webSocketClientContainer"
channel="emrOutboundChannel"/>
<int-websocket:outbound-channel-adapter id="webSocketClientOutboundAdapter"
container="webSocketClientContainer"
channel="cloudOutboundChannel"/>
它基本上是这样的组件:
CLIENT -> gateway -> transformer -> wsClient -> SERVER -> wsClient -> transformer -> gateway-reply
这里的问题是我收到错误:
org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
Websockets本质上是双向的,因此我可以在不发送任何内容的情况下获取任何消息,不是真正的请求/回复通道,但我需要以这种方式使用它。 websocket服务器只向先前的“请求”消息发送“回复”消息。
我需要通过网关返回websocket的响应。
更新1
我在网关之后添加了一个标题更丰富的字符串化并将回复和错误通道存储到注册表中:
(添加了“replyChannelRegistry”频道)
<int:gateway id="emrInboundGateway"
service-interface="com.roche.iconnect.emr.core.EmrMessageInjector">
<int:method name="injectMessage" request-channel="replyChannelRegistry" reply-channel="emrOutboundMessageTransformedChannel"/>
</int:gateway>
<beans:bean id="integrationHeaderChannelRegistry"
class="org.springframework.integration.channel.DefaultHeaderChannelRegistry">
<beans:constructor-arg index="0" value="${config.timeout}"/>
</beans:bean>
<int:header-enricher input-channel="replyChannelRegistry" output-channel="emrInboundMessageTransformerChannel">
<int:header-channels-to-string time-to-live-expression="${config.timeout}"/>
<int:correlation-id value="CORRELATION_ID_TEST"/>
</int:header-enricher>
现在的问题是......如何检索这些回复和错误频道?在通过系统的消息内部,我有一个可以添加到标题的唯一ID,但是如何从这个来自websocket的相关ID中获取回复和错误通道?
更新2(求助)
我猜这种情况很常见。请求到达您的API并响应此请求您必须通过违反请求/回复模式的通道从另一个系统获取信息。
您需要在某个地方存储您需要从请求中提取的唯一ID与其到达位置的通道之间的映射。需要使用您从其他系统获取的数据重新创建此唯一ID,否则无法恢复原始频道。
步骤是:
reply-channel
组件的gateway
属性。header-enricher
组件对replyChannel进行字符串化(请参阅更新1)。你不能拥有Map<String, MessageChannel>
映射(id / channel),你需要对频道进行字符串化。为此,请使用其他header-enricher
组件。我们的想法是设置将返回网关的消息的replyChannel
(确保消息的类与网关的返回类匹配),Spring会自动链接“临时内部点对点” “(我们之前将其字符串化的那个)发送到网关的reply-channel
。魔术!
<int:header-enricher input-channel="recoverOriginalChannel" output-channel="gatewayReplyChannel">
<int:reply-channel ref="yourBean" method="enrichReplyChannelHeader" />
</int:header-enricher>
完成!
答案 0 :(得分:1)
您正在丢失网关的replyChannel
标头;它是一个活动对象,无法通过websocket发送。
尝试使用message channel registry - 将频道转换为字符串,并将频道存储在注册表中; websocket服务器必须返回String值标头,以便正确关联它以使通道退出注册表。