我有一个JMS消息传递应用程序,该应用程序具有从多个JMS目的地入站的消息。消息有效负载是具有一些常见标头的JSON表示形式。我依靠ServiceActivators
上Spring的动态Jackson类型转换将其转换为实际的POJO。目前,路由选择很简单,因为通道本质上是按JSON有效负载类型划分的“数据类型”通道(它们都是JSON字符串有效负载,但JSON表示非常不同的对象类型)。
我想将全局验证逻辑应用于跨多个模式匹配通道的所有入站消息,例如"*input*"
并将无效消息转移到验证错误通道以供查看。无论消息是有效还是无效,都应提交本地JMS事务;如果消息无效,我不希望以后再发送无效消息。
我最初的想法是实现一个ChannelInterceptor
来匹配应该应用此逻辑的所有通道,但是似乎不能在ChannelInterceptor
中实现转移消息的功能。看来,我在ChannelInterceptor
中的两个选择是:
preSend
上返回null时,JMS事务是否已回滚,或者这些都不是所需的行为。应始终提交JMS本地事务(没有其他错误),并且消息应发送到原始目的地,或转移到无效的消息通道。
Router
可能是一个不错的选择,但是似乎没有一种方法可以将路由器应用于模式匹配的一组频道,所以我相信我必须将其应用于每个频道个别地。我希望避免这种重复。
我想到的另一个选择是突破AspectJ并在@Around
方法上实现AbstractMessageSendingTemplate.convertAndSend(destination, payload, postProcessor)
的建议。这似乎是侵入性的,但看起来似乎可行。如果有一个更好的框架直接支持的选项,我将很高兴听到它。
如果我找不到全局应用这种路由逻辑的方法,那么另一种选择可能是通过单个通道路由所有入站JMS消息。可以将自定义Router
应用于使用有效负载类型标头将消息定向到其适当的“数据类型”通道并将无效消息路由到验证错误通道的入站通道。
非常感谢!
答案 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
标头控制路由行为。因此,对我来说,逻辑看起来像:
每个流程都执行HeaderEnricher
,以在流程中所需的下一步填充replyChannel
标头。
此后,所有的扩展器将使用验证逻辑将消息流发送到Filter
组件。
如果出现故障,您会按照问题中的说明将消息发送到discardChannel
的{{1}}。
成功的话,除非Filter
标头,否则您什么都不会发送。因此,您的有效消息将返回到其原始流。
这对您有意义吗?