Spring Integration 代理网关上的入站转换器

发布于 2024-08-04 16:03:42 字数 1568 浏览 9 评论 0原文

我想配置一个看起来像这样的流程:

Method Call -> Dynamic Proxy Gateway -> Channel -> Service Activator -> Method Call
             ^---------- Transformer <- Channel <-             [return value]

实际上,我想以某种方式访问​​ Spring Integration 创建的隐藏通道并将返回消息有效负载转换为不同的消息类型。

一个简单的解决方案乍一看可能是在网关上配置默认回复通道,问题是我使用 OSGi 在捆绑包之间共享通道。服务激活器由捆绑包“B”提供,并为传入请求提供共享通道(它充当数据提供者服务)。捆绑包“A”需要一些数据,因此它请求这些数据,但需要其他格式的结果。请注意,如果捆绑包“B”能够使用捆绑包“A”指定的默认回复通道,则捆绑包“A”必须共享它。这一切都很公平,但是我在 OSGi 中存在循环依赖,并且什么都不会启动。

似乎这里的另一个解决方案是在服务激活器上定义输出通道,但这遇到了稍微不同的问题。假设我共享捆绑包“B”的输出通道,我已经减轻了循环依赖问题,但现在每当有人从捆绑包“A”请求某些内容时,回复都会发送给连接到输出通道的每个人——这也是不可取的。

[编辑:我在这里的意思是,如果“B”为其服务激活器共享输入和输出通道,那么绑定到“B”输出通道的任何人都将收到任何人请求的结果到“B”的输入通道——期望的行为是回复直接针对请求者。

我应该注意,这里的转换器仅在 Bundle A 的上下文中才有意义。Bundle B 提供了一项服务(对于我无法控制的所有意图和目的)。特定于捆绑包 A 的需求的转换应该驻留在捆绑包 A 中。]

因此,我认为我真正需要的是能够在对动态代理网关的回复上配置转换器,但尽我所能,但我做不到在 Spring Integration 手册中找到这样的设备。一如既往,我们将不胜感激。

--

编辑 2:我在这里尝试了另外两种策略:

  1. 使用引用 Bundle B 中的 OSGi 共享通道的服务激活器

    结果是返回的元素是 GenericMessageType —— 可以对其进行转换。 GenericMessageType 实际上是服务激活器必须指向的“发送”方法的布尔结果,而不是回复消息。因此,此方法不起作用

  2. 使用 header-enricher 设置 REPLY_CHANNEL 并将回复通道作为参考而不是值传递。

    此技术不起作用,当设置网关的default-reply-channel时,REPLY_CHANNEL标头元素似乎被忽略(并且default-reply-channel必须 em> 被设置)。

I'd like to configure a process that looks something like:

Method Call -> Dynamic Proxy Gateway -> Channel -> Service Activator -> Method Call
             ^---------- Transformer <- Channel <-             [return value]

Effectively, I'd like to somehow access the hidden channel Spring Integration creates and transform the return message payload into a different message type.

A simple solution may at first appear to be configuring a default-reply-channel on the gateway, the issue is that I'm sharing the channel between bundles using OSGi. The Service Activator is provided by Bundle "B", and offers a shared channel for incoming requests (it acts as a data provider service). Bundle "A" requires some data, so it requests it, but needs the result in an alternate format. Note that if Bundle "B" were to be able to use the default-reply-channel specified by Bundle "A" then Bundle "A" must share it. That's all fair and well, but then I have a circular dependency in OSGi, and nothing would start.

It seems like another solution here would be to define an output-channel on the Service Activator, but this suffers from a slightly different problem. Assuming I share the output-channel from Bundle "B" I've mitigated the circular dependency issue, but now anytime someone requests something from Bundle "A" the reply goes to everyone attached to the output channel -- this, too, is undesirable.

[Edit: What I mean here is that if "B" shares both an input and an output channel for its service activator then anyone bound to "B"'s output channel will receive the result of anyone's request to "B"'s input channel -- and the desired behavior is that the replies are directed at the requestors.

I should note that the transformer here makes sense only in the context of Bundle A. Bundle B provides a service (for all intents and purposes one that I have no control over). The transformation, specific to the needs of Bundle A should reside in Bundle A.]

So, what I think I really need is to be able to configure a transformer on replies to a dynamic proxy gateway, but try as I might I can't find such a device in the Spring Integration manual. As always, help would be greatly appreciated.

--

Edit 2: I attempted two other tactics here:

  1. Use a service-activator that refers to the OSGi shared channel from Bundle B

    The result was that the returned element was a GenericMessageType -- which it could be possible to transform. The GenericMessageType is really the boolean result of the "send" method which the service-activator must point to, not the reply message. So this method does not work.

  2. Use a header-enricher to set REPLY_CHANNEL and pass the reply channel as a reference rather than a value.

    This technique did not work, the REPLY_CHANNEL header element appears to be ignored when the default-reply-channel of the gateway is set (and the default-reply-channel must be set).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苄①跕圉湢 2024-08-11 16:03:42

理论上,真正的答案是使用链条。

捆绑包 A 的配置看起来与捆绑包 B 类似,

<si:gateway id="gw" default-request-channel="xyz" />
<si:channel id="xyz" />
<si:chain input-channel="xyz" />
    <si:service-activator />
    <si:transformer />
</si:chain>

请注意,捆绑包 B 的配置未更改,并且仅通过 OSGi 共享单个通道以供捆绑包 A 或任何第三捆绑包访问。

服务激活器有两个选项可用:

  1. 通过 OSGi 共享服务
  2. 自定义服务,只需为预转换返回的数据类型调用代理网关。

捆绑包 A 中的代理网关将注入某些输入通道“xyz”,并且最终隐含的返回通道将包含所需的转换后的内容。

该解决方案与 SingleShot 提出的解决方案几乎相同,但是这里我们阻止通过 OSGi 共享真实服务,从而维护捆绑边界。

In theory the real answer here is to use a chain.

The configuration for Bundle A will look something like

<si:gateway id="gw" default-request-channel="xyz" />
<si:channel id="xyz" />
<si:chain input-channel="xyz" />
    <si:service-activator />
    <si:transformer />
</si:chain>

Note for Bundle B the configuration is unchanged and only a single channel is shared through OSGi for access by Bundle A or any tertiary bundles.

Two options for the service-activator are available:

  1. Shared service through OSGi
  2. Custom service that simply invokes a proxy-gateway for the pre-transformation returned data type.

The proxy-gateway in Bundle A will inject into some input-channel "xyz" and ultimately the implied return channel will contained the transformed content as desired.

This solution is nearly the same as the one proposed by SingleShot, however here we prevent the sharing of a real service through OSGi, maintaining bundle boundaries.

吲‖鸣 2024-08-11 16:03:42

我对你的问题描述有点困惑。我理解循环依赖方面和变压器方面,但我不太确定“答复会发送给附加到 A 的每个人”。

听起来您可能希望为 B 有两个服务激活器。您在 B 中现有的一个服务激活器将保留,并且大多数客户都会使用它。另一个将进入 A,并且仅使用 A 中定义的通道。这将防止从 A 到 B 的请求导致 A 外部的组件收到响应。

这应该会使转换问题变得更容易。转换器从一个通道获取消息,对其进行转换,然后将其放置在另一个通道上。只要在A中添加一个就可以了。

因此,在 A 中,您将拥有这些组件,只能由 A 使用:

  • 网关
  • 输入通道
  • B 的服务激活器
  • 输出通道
  • 变压器
  • 转换后的输出通道

在 B 中,您将拥有可供任何人使用的:

  • 输入通道
  • 服务激活器B
  • 输出通道

A 依赖于 B,但 B 不依赖于 A。

这样可以吗?

I'm a bit confused by your problem description. I understand the circular dependency aspect, and the transformer aspect, but I'm not so sure about "the reply goes to everyone attached to A".

It kind of sounds like you might want to have two service activators for B. Your existing one in B would stay, and most clients would use it. The other one would go in A, and would only use channels defined in A. This would prevent requests from A to B from resulting in responses being received by components outside A.

This should make the problem of transformation easier. Transformers take a message from one channel, transform it, and place it on another. Just add one in A and you should be good.

So in A you would have these components, only useable by A:

  • a gateway
  • an input channel
  • a service activator for B
  • an output channel
  • a transformer
  • a transformed output channel

In B you would have, useable by anyone:

  • an input channel
  • a service activator for B
  • an output channel

A depends on B, but B does not depend on A.

Will that work?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文