1

I am using java dsl to configure sfp outbound flow.

Gateway:

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

Config:

@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() {
...
}

How can i configure flow to make my gateway reply with Messages that were failed? In other words i want my gateway to be able to return list of messages which were failed, not void.

I marked gateway with @MessagingGateway(errorChannel = "errorChannel")

and wrote error channel

@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();
}

and in case of some errors(i.e. no connection to SFTP) i get only one error (payload of first message in list). Where should i put Advice to aggregate all messages?

arctg
  • 11
  • 4

1 Answers1

0

This is not the question to Spring Integration Java DSL.

This is mostly a design and architecture task.

Currently you don't have any choice because you use Sftp.outboundAdapter() which is one-way, therefore without any reply. And your SftpGateway is ready for that behavior with the void return type.

If you have a downstream errorr, you can only throw them or catch and send to some error-channel.

According to your request of:

i want my gateway to be able to return list of messages which were failed, not void.

I'd say it depends. Actually it is just return from your gateway. So, if you return an empty list into gateway that may mean that there is no errors.

Since Java doesn't provide multi-return capabilities we don't have choice unless do something in our stream which builds that single message to return. As we decided list of failed messages.

Since you have there .split(), you should look into .aggregate() to build a single reply.

Aggregator correlates with the Splitter enough easy, via default applySequence = true.

To send to aggregator I'd suggest to take a look into ExpressionEvaluatingRequestHandlerAdvice on the Sftp.outboundAdapter() endpoint (second param of the .handle()). With that you should send both good and bad messages to the same .aggregate() flow. Than you can iterate a result list to clean up it from the good result. The result after that can be send to the SftpGateway using replyChannel header.

I understand that it sounds a bit complicated, but what you want doesn't exist out-of-the-box. Need to think and play yourself to figure out what can be reached.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Artem, thank you for reply! Could you provide some example with ExpressionEvaluatingRequestHandlerAdvice? – arctg Sep 14 '16 at 15:06
  • It always not good to use `errorChannel` for such a custom logic. This one is global and used as a default error-channel in many other async components: http://docs.spring.io/spring-integration/reference/html/configuration.html#namespace-errorhandler – Artem Bilan Sep 14 '16 at 17:32
  • Right, you can throw only one exception, as well as return only one reply. That works here exactly like in raw Java. No choice. – Artem Bilan Sep 14 '16 at 17:33
  • If you would like to have collected errors for all splitted items and don't impact others from one, you should look into aggregator solution. And yes, take a look into `ExpressionEvaluatingRequestHandlerAdvice` and its `trapException` option: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#expression-advice – Artem Bilan Sep 14 '16 at 17:35
  • As I said: you have to place it into `.advice()` of the second `.handle()` argument. For example email sending case: `e -> e.id("mailOut").advice(afterMailAdvice())` – Artem Bilan Sep 14 '16 at 17:36
  • Should i place "sftp-channel" in `e.id()`? Or here should be name of reply channel? – arctg Sep 16 '16 at 09:49
  • `e.id()` is an endpoint bean name. You can live without it and Framework will generates its name for you. The reply channel must be assumed in the end of process, e.g. as an outcome of `.aggregate()`. I mean that typically you don't need to worry about `replyChannel` - just only use request-reply component (e.g. `.handle()` or the same `.aggregate()` is that one) and don't specify an `outputChannel`. In terms of Java DSL you don't need any EIP-method afterwards. – Artem Bilan Sep 16 '16 at 13:51