2
votes

I'am using the inbound-channel-adapter from Spring Integration to retrieve files over sftp from a remote server. Everything works fine. But I have an additional requirement: after a file is received on the local side, that file needs to moved to a "send" directory on the remote server.

The "SFTP Outbound Gateway" has the appropriate method for that move action, but my problem is when to call it.

Situation: 10 files on remote server, 0 on local server When I start my application it will receive all 10 files from the remote server and write them to my local file system. Perfect.

Situation: 1 file on remote server, 10 on local server In this situation the remote file is received, but for every file on the local file system the receive method of the QueueChannel is also called. Example log from one file: (file1.zip)

18:12:52.118 [task-scheduler-1] INFO  o.s.i.file.FileReadingMessageSource - Created message: [[Payload File content=C:\Downloads\sftpTest\file1.zip][Headers=...]
18:12:52.119 [task-scheduler-1] DEBUG o.s.i.e.SourcePollingChannelAdapter - Poll resulted in Message: [Payload File content=C:\Downloads\sftpTest\file1.zip][Headers=...]
18:12:52.119 [task-scheduler-1] DEBUG o.s.integration.channel.QueueChannel - preSend on channel 'fromChannel', message: [Payload File content=C:\Downloads\sftpTest\file1.zip][...]
18:12:52.119 [task-scheduler-1] DEBUG o.s.integration.channel.QueueChannel - postSend (sent=true) on channel 'fromChannel', message: [Payload File content=C:\Downloads\sftpTest\file1.zip][Headers=...]
18:12:52.119 [main] DEBUG o.s.integration.channel.QueueChannel - postReceive on channel 'fromChannel', message: [Payload File content=C:\Downloads\sftpTest\file1.zip][Headers=......]

So even when the file it not physicaly retreived from the remote server, the channel.receive() method will still receive a message with that file as payload. This confuses me, because I can't determine from the message if the file was already on the local file system or was just retrieved from the remote server. I experimented using a custom org.springframework.messaging.support.ChannelInterceptorAdapter, FileFilter, ServiceActivator, but the problem still remains.

My application will process high volumes, so sending the received file to the required directory on the remote server is not an option. And also simply trying to move the file remote for every message that is locally received, is not an option since it will clutter the logfiles with exceptions of not being able to move the file. This way in case of an real error situation the problem will not be detected.

One solution might be a hook in the method copyFileToLocalDirectory of the org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer. There is a check performed if the remote file should be deleted and that loop is only called for the files that were actually transferred from the remote server. My attempts to override this method and add my move behaviour did not succeed, since Spring has already instantiated the classes that will handle this.

So what is the best way to achieve this? I know the problem will probably be located between my keyboard and my chair, but I've run out of options and any help is highly appreciated.

Thanks a lot,

Frank

1
Share your config, pleaseArtem Bilan

1 Answers

1
votes

You would probably be better off using MGET and an outbound gateway to retrieve the files instead of using the inbound adapter which, as you say, is two-stage - synchronize, and emit message(s) for file(s) in the local dir (unless you use a persistent file list filter, in which case you'll only see "new" files).