我处于请求/回复场景,并且收到需要通过同一输入连接回复的请求。为了给出响应,我需要向另一个系统发出 websocket 请求。现在,我正在以这种方式将输出 channel 连接到网关的回复 channel (我使用变压器来调整传入消息):
<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 本质上是双向的,因此我可以在不发送任何内容的情况下获取任何消息,这不是真正的请求/回复 channel ,但我需要以这种方式使用它。 websocket 服务器只发送“回复”消息到之前的“请求”消息。
我需要通过网关返回websocket的响应。
<小时/>更新1
我在网关之后添加了一个 header 丰富器,以字符串化并将回复和错误 channel 存储到注册表中:
(添加了“replyChannelRegistry” channel )
<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>
现在的问题是...我如何检索这些回复和错误 channel ?在通过系统的消息中,我有一个可以添加到 header 的唯一 ID,但是如何从来自 Websocket 的相关 ID 中获取回复和错误 channel ?
更新 2(已解决)
我想这种情况很常见。请求到达您的 API,要响应此请求,您必须通过打破请求/答复模式的 channel 从另一个系统获取信息。
您需要在某个地方存储您需要从请求中提取的唯一 ID 与请求到达的 channel 之间的映射。这个唯一的 ID 需要使用您从其他系统获取的数据重新创建,否则您无法恢复原始 channel 。
步骤是:
- 请求来了。
- 使用
reply-channel
gateway
的属性(property)组件。 - 使用
header-enricher
对replyChannel进行字符串化组件(请参阅更新 1)。您不能拥有Map<String, MessageChannel>
映射(id/ channel ),您需要对 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>
完成!
最佳答案
您正在丢失网关的 replyChannel
header ;它是一个 Activity 对象,无法通过 websocket 发送。
尝试使用 message channel registry - 将 channel 转换为字符串,并将 channel 存储在注册表中; websocket 服务器必须返回字符串值 header ,以便可以正确关联以从注册表中获取 channel 。
关于java - 将 websocket 入站 channel 适配器连接到网关的回复 channel ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45938571/