Spring集成,将无效消息全局转移到另一个目标

时间:2018-10-12 19:56:18

标签: java spring spring-integration enterprise-integration

设置

我有一个JMS消息传递应用程序,该应用程序具有从多个JMS目的地入站的消息。消息有效负载是具有一些常见标头的JSON表示形式。我依靠ServiceActivators上Spring的动态Jackson类型转换将其转换为实际的POJO。目前,路由选择很简单,因为通道本质上是按JSON有效负载类型划分的“数据类型”通道(它们都是JSON字符串有效负载,但JSON表示非常不同的对象类型)。

问题

我想将全局验证逻辑应用于跨多个模式匹配通道的所有入站消息,例如"*input*"并将无效消息转移到验证错误通道以供查看。无论消息是有效还是无效,都应提交本地JMS事务;如果消息无效,我不希望以后再发送无效消息。

考虑的潜在选项

频道拦截器

我最初的想法是实现一个ChannelInterceptor来匹配应该应用此逻辑的所有通道,但是似乎不能在ChannelInterceptor中实现转移消息的功能。看来,我在ChannelInterceptor中的两个选择是:

  1. 在拦截器在preSend上返回null时,JMS事务是否已回滚,或者
  2. 无效消息仍会发送到原始目的地。

这些都不是所需的行为。应始终提交JMS本地事务(没有其他错误),并且消息应发送到原始目的地,或转移到无效的消息通道。

路由器

Router可能是一个不错的选择,但是似乎没有一种方法可以将路由器应用于模式匹配的一组频道,所以我相信我必须将其应用于每个频道个别地。我希望避免这种重复。

AspectJ切入点

我想到的另一个选择是突破AspectJ并在@Around方法上实现AbstractMessageSendingTemplate.convertAndSend(destination, payload, postProcessor)的建议。这似乎是侵入性的,但看起来似乎可行。如果有一个更好的框架直接支持的选项,我将很高兴听到它。

带有有效负载路由的公用输入通道

如果我找不到全局应用这种路由逻辑的方法,那么另一种选择可能是通过单个通道路由所有入站JMS消息。可以将自定义Router应用于使用有效负载类型标头将消息定向到其适当的“数据类型”通道并将无效消息路由到验证错误通道的入站通道。

问题

  • 是否可以将这种类型的消息转移应用于模式匹配的一组信道?
  • 我是否错过了Spring Integration框架的一项重要功能,它将使我的考虑之一发挥作用?
  • 如果没有,是否有比我提到的更好的EIP选项?

非常感谢!

2 个答案:

答案 0 :(得分:1)

  

我最初的想法是实现一个ChannelInterceptor来匹配应该应用此逻辑的所有通道,但是似乎不能在ChannelInterceptor中实现转移消息的功能

是什么让您相信这一点? preSend()可以返回null,从而有效终止操作;只需将失败的验证发送到公共通道并返回null

/**
 * Invoked before the Message is actually sent to the channel.
 * This allows for modification of the Message if necessary.
 * If this method returns {@code null} then the actual
 * send invocation will not occur.
 */
@Nullable
default Message<?> preSend(Message<?> message, MessageChannel channel) {
    return message;
}

这将在入站适配器上引起MessageDeliveryException,但是您可以简单地在错误通道流中吸收它。

答案 1 :(得分:1)

我的位置在全局ChannelInterceptor中不这样做,因为很容易陷入不应该受到这种过滤逻辑影响的通道的情况。

您始终可以将所有消息发送到同一通道以使用通用逻辑。在发送到验证通道之前,可以通过填充的replyChannel标头控制路由行为。因此,对我来说,逻辑看起来像:

  1. 每个流程都执行HeaderEnricher,以在流程中所需的下一步填充replyChannel标头。

  2. 此后,所有的扩展器将使用验证逻辑将消息流发送到Filter组件。

  3. 如果出现故障,您会按照问题中的说明将消息发送到discardChannel的{​​{1}}。

  4. 成功的话,除非Filter标头,否则您什么都不会发送。因此,您的有效消息将返回到其原始流。

这对您有意义吗?