【问题标题】:Connect websocket inbound channel adapter to the reply channel of a gateway将 websocket 入站通道适配器连接到网关的回复通道
【发布时间】:2017-08-29 11:58:01
【问题描述】:

我处于请求/回复场景中,我收到需要通过相同输入连接回复的请求。要给出响应,我需要向另一个系统发出 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

Header enricher registry

我在网关之后添加了一个标头丰富器,用于对回复和错误通道进行字符串化并将其存储到注册表中:

(添加了“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,否则无法恢复原始频道。

步骤是:

  1. 请求来了。
  2. 使用gateway 组件的reply-channel 属性。
  3. 使用header-enricher 组件对replyChannel 进行字符串化(参见更新1)。你不能有Map&lt;String, MessageChannel&gt; 映射(id/channel),你需要对频道进行字符串化。
  4. 请求响应数据。
  5. 获取响应数据。
  6. 现在您需要通过相同的原始连接发送回复。
  7. 为此,请使用另一个 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>

  8. 完成!

【问题讨论】:

    标签: java spring-integration


    【解决方案1】:

    您正在丢失网关的 replyChannel 标头;它是一个活动对象,不能通过 websocket 发送。

    尝试使用message channel registry - 将频道转换为字符串,并将频道存储在注册表中; websocket 服务器必须返回 String 值标头,以便正确关联以将通道从注册表中取出。

    【讨论】:

    • 回复和错误通道已正确字符串化,并可能存储在注册表中。我还添加了一个correlationId 标头,我可以在那里存储一个唯一ID。现在我可以根据correlationId 标头属性从注册表中检索回复通道吗?
    • 你可以;但只要发送到网关的reply-channel 的消息具有具有适当字符串值的replyChannel 标头,框架就会自动执行此操作。它不使用correlationId 标头,它使用带有字符串化值的replyChannel 标头在注册表中查找通道。
    猜你喜欢
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 2014-06-29
    • 2016-01-18
    相关资源
    最近更新 更多