Я использую интеграцию spring для изменения потока после завершения конкретной попытки. Мой bean-компонент IntegrationFlow для errorResponse выглядит следующим образом:
@Bean
public IntegrationFlow errorMailResponse(@Qualifier(ERROR_CHANNEL) PollableChannel errorChannel) {
return IntegrationFlows.from(errorChannel)
.handle(MessagingException.class, (payload, headers) -> handleMessageException(payload),
e -> e.poller(p -> p.fixedDelay(pollerInterval)))
.channel(NO_OUTPUT_CHANNEL)
.get();
}
Если метод handleMessageException
возвращает объект, я хочу, чтобы поток продолжался до определенного канала — MAIN_EVENTS_CHANNEL, если handleMessageException
возвращает null, я хочу продолжить до NO_OUTPUT_CHANNEL.
Возможно ли это достичь с интеграцией Spring? Я пытался использовать подпоток, но я не уверен, что это так. https://docs.spring.io/spring-integration/reference/html/dsl.html#java-dsl-подпотоки
@Bean
public IntegrationFlow errorMailResponse(@Qualifier(ERROR_CHANNEL) PollableChannel errorChannel) {
return IntegrationFlows.from(errorChannel)
.handle(MessagingException.class, (payload, headers) -> handleMailMessageException(payload),
e -> e.poller(p -> p.fixedDelay(pollerInterval)))
.publishSubscribeChannel(subscription -> subscription
.subscribe(subflow -> subflow
.<MailPojo>handle((payload, headers) -> {
// if if result handleMessageException == null
})
.channel(NO_OUTPUT_CHANNEL))
.subscribe(subflow -> subflow
.<MailPojo>handle((payload, headers) -> {
// if result handleMessageException !=null
})
.channel(MAIN_EVENTS_CHANNEL)))
.get();
}
Любая помощь приветствуется.
Во-первых, null
не payload
. Поэтому в большинстве случаев обмен сообщениями не поддерживает null
. Поток интеграции просто останавливается в точке, где вы возвращаетесь null
: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#service-activator-namespace
The service activator is one of those components that is not required to produce a reply message. If your method returns null or has a void return type, the service activator exits after the method invocation, without any signals.
Итак, ваше предположение о принятии логического решения неверно с Spring Integration. Вам нужно подумать о том, что может быть использовано в качестве сигнала для такого NO_OUTPUT_CHANNEL
. Вы можете создать искусственный NullType
и использовать PayloadTypeRouter
, чтобы определить, когда идти дальше, в соответствии с типом полезной нагрузки, возвращенным из вашего handleMailMessageException()
:
.<Object, Class<?>>route(Object::getClass, m -> m
.channelMapping(MailPojo.class, MAIN_EVENTS_CHANNEL)
.channelMapping(NullType.class, NO_OUTPUT_CHANNEL))
Другой способ — использовать Optional
и проверить его содержимое в функции роутера. В любом случае вам нужно использовать маршрутизатор.
Оба варианта действительны. Выбирайте то, что лучше работает для вас и легче для понимания.
Еще один момент: могу ли я изменить полезную нагрузку в ChannelMapping или мне нужно использовать что-то еще, например subFlowMapping?
Нет, цель роутера — просто проложить маршрут к тому или иному каналу (или нескольким). Ручка и преобразование предназначены для этой цели. Да, subFlow можно использовать как точку входа для дальнейшей логики после маршрутизации
Вы имеете в виду использование subFlowMapping
следующим образом: .<Object, Class<?>>route(Object::getClass, m -> m .channelMapping(MailPojo.class, MAIN_EVENTS_CHANNEL) .subFlowMapping(Integer.class, sf -> sf.<MailPojo>handle((p, h) -> handleRetryCounter(p))) .channelMapping(EmptyType.class, NO_OUTPUT_CHANNEL)) .get(); }
В handleRetryCounter()
я подсчитываю, сколько раз я пытаюсь отправить сообщение. Если количество > 3, поток должен быть прекращен.
Это нормально. Но вы видите, что вы делаете это в ручке. Было неправильно сравнивать отображение с дескриптором. Вероятно, вам нужно изучить рекомендации по повторным попыткам вместо этой пользовательской логики: docs.spring.io/spring-integration/docs/current/reference/html/…
Спасибо за ваш ответ! Итак, после
.handle
я добавляю.route
или удаляю.handle
и вместо этого использую один.route
?