Search code examples
javaspringspring-integrationsftpspring-integration-sftp

Spring SFTP Adapter InboundAdapter with RotatingServerAdvice - Getting full path


Using spring-integration-sftp: 5.1.3

I have an inbound setup with RotatingServerAdvice that is watching two directories:

--inbox
-----dir1
-----dir2

Watching: inbox/dir1 and inbox/dir2

Local directory: temp/sftp

When I put a file in inbox/dir1/file1.txt, my handler is called as expected and file1.txt is copied to a temp/sftp/file1.txt (<- this is the problem, details below)

Problem:

My use case is that when I get the file, I want to know which remote subdirectory it's from. If the local file was transferred to temp/sftp/inbox/dir1/file1.txt then I could tell that it came from /inbox/dir1 and I can perform some operations on the remote sftp on this directory.

Why is the file being transferred flat and not in subdirectories on the local directory? Any help would be appreciated.

Inbound Adapter:

@Bean
public IntegrationFlow sftpInboundsFlow(DelegatingSessionFactory<LsEntry> delegatingSessionFactory,
    SftpServiceActivator serviceActivator) throws JSchException {

    SftpConnection config = sftpConnectionConfig.getSftpConnectionConfig(delegatingSessionFactory);

    return IntegrationFlows
        .from(Sftp.inboundAdapter(delegatingSessionFactory)
                .preserveTimestamp(true)
                .autoCreateLocalDirectory(true)
                .preserveTimestamp(true)
                .remoteDirectory("*")
                .filter(new CopartFileFilter(Pattern.compile(".*")))
                .localDirectory(new File( System.getProperty("java.io.tmpdir") + "/" + config.getLocalDirectory())),
                e -> e.id("inboundSftpChannel")
                .autoStartup(true)
                .poller(Pollers
                    .fixedDelay(config.getPollerInterval())
                    .advice(advice(delegatingSessionFactory))
                    .maxMessagesPerPoll(1)))
        .handle(m -> serviceActivator.handleMessage(m))
        .get();
}

File info on handler:

file: file1.txt, parent: /var/folders/sd/5k6jwzgs2hj2q165b6x9pql55mp8t7/T/sftp, headers {file_originalFile=/var/folders/sd/5k6jwzgs2hj2q165b6x9pql55mp8t7/T/sftp/file1.txt, id=d2620539-ab0d-2590-9b51-f4dfb442a74a, file_name=file1.txt, file_relativePath=file1.txt, timestamp=1581371879819}

Try 1:

I think this is similar to the first approach mentioned.

.localFilenameExpression("#remoteDirectory + '/' + #this")

It correctly puts the file under temp/sftp/inbox/dir1/file1.txt. The problem now is that the message I get is for this directory:

temp/sftp/inbox

Not the file1.txt


Solution

  • Had some trouble implementing the solutions suggested because of me being new to this. I went with a different approach because it worked fine for my requirement:

    In the sftpInboundsFlow

    .localFilenameExpression("#remoteDirectory.replaceAll('/', '-') + '_' + #this")
    

    This places the files in a flat structure in the local temp directory.

     temp/sftp:
           inbox-dir1_file1.txt
    

    Then in the handler:

    1. Extract remote directory from file name:

      public String extractRemoteDir(File ackFile) {
          String fileName = ackFile.getName();
          return fileName.split("_")[0].replaceAll("-", "/");
      }
      
    2. Custom logic on the remote dir
    3. Delete ackFile

    One thing that would make this less hacky would be to to know the remote directory in the local file handler (maybe in the headers), but I didn't find a way to find that.