Reputation: 23
When using Spring Integration's SFTP Session Factory (with Java config), I'd like to set the remote SFTP server directory dynamically. The Spring docs say this is possible:
Spring Integration SFTP Adapters
SpEL and the SFTP Outbound Adapter
As with many other components in Spring Integration, you can benefit from the Spring Expression Language (SpEL) support when configuring an SFTP Outbound Channel Adapter, by specifying two attributes
remote-directory-expression
andremote-filename-generator-expression
(see above). The expression evaluation context will have the Message as its root object, thus allowing you to provide expressions which can dynamically compute the file name or the existing directory path based on the data in the Message (either from payload or headers). In the example above we are defining theremote-filename-generator-expression
attribute with an expression value that computes the file name based on its original name while also appending a suffix: -foo.
But I'm having troubles implementing this. I can't seem to find a good example that uses Spring's SpEL expression language. The code below works, and sends my files to the root directory as it is below, or a specific directory if I enter one in the LiteralExpression. But I'd like to swap out the LiteralExpression expression with a SpelExpression that uses the "path" header, similar to what I've done with the "file" header which dynamically adjusts the filename being uploaded.
@Configuration
public class SftpConfig {
@Autowired
private SftpSettings sftpSettings;
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(sftpSettings.getHostname());
factory.setPort(sftpSettings.getPort());
factory.setUser(sftpSettings.getUsername());
factory.setPassword(sftpSettings.getPassword());
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
}
@Bean
@ServiceActivator(inputChannel = "toSftpChannel")
public MessageHandler handler() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setAutoCreateDirectory(true); // automatically create the remote directory
handler.setRemoteDirectoryExpression(new LiteralExpression(""));
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return (String) message.getHeaders().get("filename");
}
});
return handler;
}
@MessagingGateway
public interface UploadGateway {
@Gateway(requestChannel = "toSftpChannel")
void upload(@Payload byte[] file, @Header("filename") String filename, @Header("path") String path);
}
}
To initiate the file upload I execute this code
@Autowired
private UploadGateway gateway;
byte[] file = "test".getBytes();
path = "mydirectory";
filename = "myfilename";
gateway.upload(file, filename, path); // edited to correct parameter order error
Upvotes: 2
Views: 8482
Reputation: 121177
The SpEL expression can be really complex and dynamic. For that purpose you have to declare parser:
ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser()
and use it for this expression parsing:
handler.setRemoteDirectoryExpression(EXPRESSION_PARSER.parseExpression("headers['path']"));
And the result Expression
object will be evaluated against each request message.
See more info in the Reference Manual.
Upvotes: 6