2

I'm having an issue with the SFTP outbound gateway using DSL. I want to use a outbound gateway to send a file, then continue my flow. The problem is that I have an exception telling me:

IllegalArgumentException: 'remoteDirectoryExpression' is required

I saw that I can use a RemoteFileTemplate where I can set the sftp session factory plus the remote directory information, but the directory I wan't is defined in my flow by the code put in the header just before the launch of the batch.

    @Bean
public IntegrationFlow orderServiceFlow() {
    return f -> f
            .handleWithAdapter(h -> h.httpGateway("myUrl")
                    .httpMethod(HttpMethod.GET)
                    .expectedResponseType(List.class)
            )
            .split()
            .channel(batchLaunchChannel());
}

@Bean
public DirectChannel batchLaunchChannel() {
    return MessageChannels.direct("batchLaunchChannel").get();
}

@Bean
public IntegrationFlow batchLaunchFlow() {
    return IntegrationFlows.from(batchLaunchChannel())
            .enrichHeaders(h -> h
                    .headerExpression("oiCode", "payload")
            )
            .transform((GenericTransformer<String, JobLaunchRequest>) message -> {
                JobParameters jobParameters = new JobParametersBuilder()
                        .addDate("exec_date", new Date())
                        .addString("oiCode", message)
                        .toJobParameters();
                return new JobLaunchRequest(orderServiceJob, jobParameters);
            })
            .handle(new JobLaunchingMessageHandler(jobLauncher))

            .enrichHeaders(h -> h
                    .headerExpression("jobExecution", "payload")
            )
            .handle((p, h) -> {
                //Logic to retreive file...
                return new File("");
            })
            .handle(Sftp.outboundGateway(sftpSessionFactory,
                    AbstractRemoteFileOutboundGateway.Command.PUT,
                    "payload")
            )
            .get();
}

I don't see how I can tell my outbound gateway which will be the directory depending what is in my header.

2 Answers2

2

The Sftp.outboundGateway() has an overloaded version with the RemoteFileTemplate. So, you need to instantiate SftpRemoteFileTemplate bean and configure its:

/**
 * Set the remote directory expression used to determine the remote directory to which
 * files will be sent.
 * @param remoteDirectoryExpression the remote directory expression.
 */
public void setRemoteDirectoryExpression(Expression remoteDirectoryExpression) {

This one can be like FunctionExpression:

setRemoteDirectoryExpression(m -> m.getHeaders().get("remoteDireHeader"))
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks for the answer, but I have difficulties to know how to set the directory expression inside my flow. If I understand, I will declare the RemoteFileTemplate as a Bean, before to call it in my gateway, I need to add a step to change the directory expression? – Damien Walle Jan 19 '18 at 15:32
  • ??? Why would one need to change the directory expression? You said that you have a header on the matter, so all you need is an expression to get access to the header on each message. That's exactly my answer does. Then you need to use that `RemoteFileTemplate` for the `Sftp.outboundGateway()` definition. – Artem Bilan Jan 19 '18 at 15:39
  • Sorry, I'm not used to SpelExpression, I thought I had to send the Expression from my flow but no. I understand now. Thanks – Damien Walle Jan 19 '18 at 15:58
1

Before I got an answer, I came with this solution but I'm not sure it's a good one.

// flow //
 .handle((p, h) -> {
    //Logic to retreive file...
    return new File("");
})
.handle(
        Sftp.outboundGateway(
                remoteFileTemplate(new SpelExpressionParser().parseExpression("headers['oiCode']")),
                AbstractRemoteFileOutboundGateway.Command.PUT,
                "payload")
)
.handle(// next steps //)
.get();

public RemoteFileTemplate remoteFileTemplate(Expression directory) throws Exception {
        RemoteFileTemplate template = new SftpRemoteFileTemplate(sftpSessionFactory);
        template.setRemoteDirectoryExpression(directory);
        template.setAutoCreateDirectory(true);
        template.afterPropertiesSet();
        return template;
}

But this provoke a warn because of exception thrown by the ExpresionUtils java.lang.RuntimeException: No beanFactory

  • 1
    I answered you exactly the same. Only the problem that you don't declare `RemoteFileTemplate` as a bean. That's why you have that exception. – Artem Bilan Jan 19 '18 at 15:41