Below is the configuration I am using
@Autowired
private SftpRemoteFileTemplate outboundTemplate;
@Autowired
private SftpConfig config;
@Bean
@ServiceActivator(inputChannel = "sftpOutputGenericChannel")
public MessageHandler simplehandler() {
SftpMessageHandler handler = new SftpMessageHandler(outboundTemplate, FileExistsMode.APPEND);
handler.setRemoteDirectoryExpression(new LiteralExpression(config.getDirectory()));
handler.setFileNameGenerator((Message<?> message) -> ((String) message.getHeaders().get(KEY)));
handler.setUseTemporaryFileName(false);
return handler;
}
I have created Sessionfactory, CachingSessionfactory and SftpRemoteFileTemplte in a seperate Config class and they are getting instantiated properly, below are the logs for the same.
2020-11-27 01:15:17.742 [main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'cachingSessionFactory'
2020-11-27 01:15:17.744 [main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'sftpSessionFactory'
2020-11-27 01:15:17.778 [main] o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from bean name 'cachingSessionFactory' via factory method to bean named 'sftpSessionFactory'
2020-11-27 01:15:17.783 [main] o.s.integration.util.SimplePool : Target pool size changed by -2147483637, now 10
2020-11-27 01:15:54.434 [main] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'outboundTemplate'
2020-11-27 01:15:54.435 [main] o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from bean name 'outboundTemplate' via factory method to bean named 'cachingSessionFactory'
When I execute this code Spring DEBUG logs shows that the file is been sent to the server successfully, but actually file is not getting uploaded to the server.
but if I change implementation of MessageHandler
to,
SftpMessageHandler handler = new SftpMessageHandler(new SftpRemoteFileTemplate(cachingSessionFactory), FileExistsMode.APPEND);
it starts working and file actually gets uploaded to the server, not sure why this is happening ?
One more observation when I use @Autowired SftpRemoteFileTemplate
with handler.setRemoteDirectoryExpressionString("headers['remote_directory']")
it works perfectly fine.
I want to understand how SftpRemoteTemplate is working here and what is the best practice suggested ?
Note : SpringBoot v2.4.0 Spring integration : 5.4.1, faced the similer issue with boot v2.2.6.RELEASE
You probably use the same
SftpRemoteFileTemplate
in other places and you also modify it over there for other options. In fact something likehandler.setRemoteDirectoryExpression()
does a delegation, and therefore mutation, to the providedSftpRemoteFileTemplate
:So, when another place does a similar modification, you end up with a race condition and your file may be transferred to a different place.
The best practice is to treat a
RemoteFileTemplate
as aprototype
and have an instance per channel adapter. Or just use another ctor - only aSessionFactory
-based:We probably need to revise the logic in the
FileTransferringMessageHandler
to reject a mutation for externally providedRemoteFileTemplate
. Feel free to raise a GH issue and we will see what we can do in the next major version, where we can do some breaking changes.