Java 集成流中的条件处理程序
我正在开发web钩子通知服务,它允许客户端订阅/取消订阅流经中间件的消息,并通过将消息负载发布到提供的回调URL来获得消息通知(根据提供的标准)。 邮件传递如下所示:Java 集成流中的条件处理程序,java,spring,spring-integration,spring-integration-dsl,Java,Spring,Spring Integration,Spring Integration Dsl,我正在开发web钩子通知服务,它允许客户端订阅/取消订阅流经中间件的消息,并通过将消息负载发布到提供的回调URL来获得消息通知(根据提供的标准)。 邮件传递如下所示: flowBuilder .enrichHeaders(e->e.header(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE,true)) .handle(Http.outboundChannelAdapter(message->
flowBuilder
.enrichHeaders(e->e.header(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE,true))
.handle(Http.outboundChannelAdapter(message-> {
String subscriptionId = message.getHeaders().get(SUBSCRIPTION_ID_HEADER_NAME, String.class);
return subscriptionsStore.get(UUID.fromString(subscriptionId)).getCallbackUrl(); //potential NPE if subscription was removed
},restTemplateBuilder.build())
.get()
如您所见,uriFunction的实现通过订阅id(消息头的一部分)从subscriptionstore
获取回调URL
我的问题是关于客户已经用他的订阅id取消订阅,而我正在寻找条件处理程序的情况
我知道我可以筛选订阅存储中仍存在订阅id的邮件,但这不是适当的解决方案,因为客户端可能会在filter
和handle
操作之间取消订阅,仍然会导致uriFunction
中出现NRE
另一个解决方案是使用回调URL注册每个标头,然后通过具有非空值的标头进行过滤,但我不想损害原始消息的标头和有效负载
我可以考虑另一种方法:将不存在的订阅的URI计算为某个静态值,并将拦截器添加到restempalte
中,以模拟HTTP OK replay来显示此特定URI值
因此,我的问题是如何通过使用标准EIP或另一个我不知道的Spring集成功能来处理这种情况
谢谢
更新
我添加了保存上下文的专用消息
类:
public static class DedicatedMessage extends GenericMessage<Object> implements MessageDecorator{
@Getter
@Transient
private Subscription subscription;
public DedicatedMessage(Subscription subscription,Object payload,Map<String,Object> headers) {
super(payload,headers);
this.subscription = subscription;
}
@Override
public Message<?> decorateMessage(Message<?> message) {
return new DedicatedMessage (subscription,message.getPayload(),message.getHeaders());
}
}
这个方法有什么问题吗?我不知道你的
NRE
缩写是什么意思,但是你可以从你的subscriptionstore.get()中抛出一个NosSubscriptionException
方法,然后在应用于其端点.advice()
链中的出站通道适配器的表达式EvaluationRequestHandlerAdvice中忽略/报告该异常。空引用异常,很抱歉,应该是NPE,在subscriptionStore.get(id)返回Null时引发。我将尝试应用建议并处理异常。您需要包装get()
并在异常返回null
时抛出异常。是的,当然,我明天将尝试您的建议。但是你不认为条件处理程序可能是spring集成中包含的候选者吗?不清楚你的意思-正如你所说的,如果我们添加一个条件,仍然存在一个竞争条件,即在条件测试和处理程序调用之间可以删除订阅。它只是使用过滤器缩短了时间窗口,但并没有消除它;如果(测试上下文){targetHandler.handle(message,context)}。。。
flowBuilder
.enrichHeaders(e->e.header(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE,true))
.handle((payload, headers) -> {
String subscriptionId = (String) headers.get(SUBSCRIPTION_ID_HEADER_NAME);
Subscription subscription = subscriptionsCache.get(UUID.fromString(subscriptionId));
return Optional.ofNullable(subscription)
.map(s-> new DedicatedMessage(s, payload,headers))
.orElse(null);
})
.handle(Http.outboundChannelAdapter(message->((DedicatedMessage)message).getSubscription().getCallbackUrl()
,restTemplateBuilder.build())
.get()