Подпоток Spring Integration в зависимости от метода .handle

Я использую интеграцию 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();
}

Любая помощь приветствуется.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
32
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, 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 и проверить его содержимое в функции роутера. В любом случае вам нужно использовать маршрутизатор.

Спасибо за ваш ответ! Итак, после .handle я добавляю .route или удаляю .handle и вместо этого использую один .route?

skywalker 17.03.2022 16:42

Оба варианта действительны. Выбирайте то, что лучше работает для вас и легче для понимания.

Artem Bilan 17.03.2022 16:46

Еще один момент: могу ли я изменить полезную нагрузку в ChannelMapping или мне нужно использовать что-то еще, например subFlowMapping?

skywalker 18.03.2022 12:37

Нет, цель роутера — просто проложить маршрут к тому или иному каналу (или нескольким). Ручка и преобразование предназначены для этой цели. Да, subFlow можно использовать как точку входа для дальнейшей логики после маршрутизации

Artem Bilan 18.03.2022 13:14

Вы имеете в виду использование 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, поток должен быть прекращен.

skywalker 18.03.2022 13:50

Это нормально. Но вы видите, что вы делаете это в ручке. Было неправильно сравнивать отображение с дескриптором. Вероятно, вам нужно изучить рекомендации по повторным попыткам вместо этой пользовательской логики: docs.spring.io/spring-integration/docs/current/reference/htm‌​l/…

Artem Bilan 18.03.2022 14:04

Другие вопросы по теме