создать канал ответа sftp для ответа с ошибкой или сообщениями, которые были отправлены безуспешно

Я использую java dsl для настройки исходящего потока sfp.

Шлюз:

@MessagingGateway
 public interface SftpGateway {
 @Gateway(requestChannel = "sftp-channel")
 void sendFiles(List<Message> messages);
}

Конфиг:

@Bean
public IntegrationFlow sftpFlow(DefaultSftpSessionFactory sftpSessionFactory) {
    return IntegrationFlows
            .from("sftp-channel")
            .split()
            .handle(Sftp.outboundAdapter(sftpSessionFactory, FileExistsMode.REPLACE)
            .useTemporaryFileName(false)
            .remoteDirectory(REMOTE_DIR_TO_CREATE).autoCreateDirectory(true)).get();
}

@Bean
public DefaultSftpSessionFactory sftpSessionFactory() {
...
}

Как я могу настроить поток, чтобы мой шлюз отвечал сообщениями, которые были неудачными? Другими словами, я хочу, чтобы мой шлюз мог возвращать список неудачных сообщений, а не недействительных.

Я отметил шлюз с помощью @MessagingGateway (errorChannel = "errorChannel")

и написал канал ошибки

@Bean
public IntegrationFlow errorFlow() {
    return IntegrationFlows.from("errorChannel").handle(new GenericHandler<MessagingException>() {

        public Message handle(MessagingException payload, Map headers) {
            System.out.println(payload.getFailedMessage().getHeaders());
            return payload.getFailedMessage();
        }
    })
            .get();
}

@Bean
public MessageChannel errorChannel() {
    return MessageChannels.direct().get();
}

и в случае некоторых ошибок (например, при отсутствии подключения к SFTP) я получаю только одну ошибку (полезная нагрузка первого сообщения в списке). Куда мне поместить совет, чтобы собрать все сообщения?


person arctg    schedule 14.09.2016    source источник


Ответы (1)


Это не вопрос Spring Integration Java DSL.

В основном это задача дизайна и архитектуры.

В настоящее время у вас нет выбора, потому что вы используете Sftp.outboundAdapter(), который является односторонним, поэтому без ответа. И ваш SftpGateway готов к такому поведению с возвращаемым типом void.

Если у вас есть обработчик ошибок нижестоящего, вы можете только выбросить их или поймать и отправить какому-нибудь error-channel.

По вашему запросу:

Я хочу, чтобы мой шлюз мог возвращать список неудачных сообщений, а не недействительных.

Я бы сказал, это зависит от обстоятельств. На самом деле это просто возврат из вашего шлюза. Итак, если вы вернете в шлюз пустой список, это может означать, что ошибок нет.

Поскольку Java не предоставляет возможности множественного возврата, у нас нет выбора, если не сделать что-то в нашем потоке, которое создает это единственное сообщение для возврата. Как мы и решили, список неудачных сообщений.

Поскольку у вас есть .split(), вам следует изучить .aggregate(), чтобы создать единый ответ.

Агрегатор достаточно легко коррелирует со сплиттером, по умолчанию applySequence = true.

Для отправки агрегатору я предлагаю взглянуть на ExpressionEvaluatingRequestHandlerAdvice на конечной точке Sftp.outboundAdapter() (второй параметр .handle()). При этом вы должны отправлять как хорошие, так и плохие сообщения в один .aggregate() поток. Затем вы можете перебирать список результатов, чтобы очистить его от хорошего результата. Результат после этого можно отправить в SftpGateway, используя заголовок replyChannel.

Я понимаю, что это звучит немного сложно, но то, что вы хотите, не существует «из коробки». Нужно думать и играть самому, чтобы понять, чего можно достичь.

person Artem Bilan    schedule 14.09.2016
comment
Артем, спасибо за ответ! Не могли бы вы привести пример с ExpressionEvaluatingRequestHandlerAdvice? - person arctg; 14.09.2016
comment
Всегда нецелесообразно использовать errorChannel для такой нестандартной логики. Этот является глобальным и используется как канал ошибок по умолчанию во многих других асинхронных компонентах: docs.spring.io/spring-integration/reference/html/ - person Artem Bilan; 14.09.2016
comment
Правильно, вы можете выбросить только одно исключение, а также вернуть только один ответ. Здесь это работает точно так же, как в сырой Java. Нет выбора. - person Artem Bilan; 14.09.2016
comment
Если вы хотите собрать ошибки для всех разделенных элементов и не повлиять на другие из одного, вам следует изучить решение агрегатора. И да, взгляните на ExpressionEvaluatingRequestHandlerAdvice и его параметр trapException: docs.spring.io/spring-integration/reference/html/ - person Artem Bilan; 14.09.2016
comment
Как я уже сказал: вы должны поместить его в .advice() второго .handle() аргумента. Например, случай отправки электронного письма: e -> e.id("mailOut").advice(afterMailAdvice()) - person Artem Bilan; 14.09.2016
comment
Стоит ли размещать sftp-канал в e.id()? Или здесь должно быть название канала ответа? - person arctg; 16.09.2016
comment
e.id() - имя bean-компонента конечной точки. Вы можете жить без него, и Framework сгенерирует для вас свое имя. Канал ответа должен быть указан в конце процесса, например в результате .aggregate(). Я имею в виду, что обычно вам не нужно беспокоиться о replyChannel - просто используйте только компонент запрос-ответ (например, .handle() или тот же .aggregate()) и не указывайте outputChannel. В терминах Java DSL вам впоследствии не потребуется никакого EIP-метода. - person Artem Bilan; 16.09.2016