I am writing an IntegrationFlow for SFTP, to copy only the latest file in remote directory, to local. I also want to avoid copying the same file twice so I added an AcceptOnceFileListFilter.
Unfortunately the remote files come in form of IGNORED_STRING_1008202211:22:33.csv, as you see there is a date-time stamp, based on which I determine the latest file, but the colon symbol is not accepted for filenames in Windows, so I had to apply a function to rename it.
Now this messes with the AcceptOnceFileListFilter, I've debugged and the original file name is checked once, then it is compared to the modified one (without colons) - so it always gets downloaded again.
Sftp.inboundAdapter(sftpSf)
.filter(new ChainFileListFilter<>() {{
addFilter(new LatestFileOnly());
addFilter(new AcceptOnceFileListFilter<>());
}})
.localFilename(new Function<String, String>() {
@Override
public String apply(String s) {
return s.replaceAll(":", "");
}
})
.autoCreateLocalDirectory(true)
.remoteDirectory(readRemoteDirectory)
.deleteRemoteFiles(false)
.preserveTimestamp(true)
.localDirectory(new File(localDirectory));
and the filter to find the latest file, from its filename:
public class LatestFileOnly implements FileListFilter<ChannelSftp.LsEntry> {
@Override
public List<ChannelSftp.LsEntry> filterFiles(ChannelSftp.LsEntry[] files) {
return Arrays.stream(files)
.max(byParsedDate)
.map(Collections::singletonList)
.orElse(Collections.emptyList());
}
public final Comparator<ChannelSftp.LsEntry> byParsedDate = Comparator.comparing(
(ChannelSftp.LsEntry o) -> {
Matcher m = pattern.matcher(o.getFilename());
if (m.find()) {
return LocalDateTime.parse(m.group(0), DateTimeFormatter.ofPattern("ddMMyyyyHH:mm:ss"));
}
return LocalDateTime.MIN;
});
}

Yes: that's the problem of the
ChannelSftp.LsEntryandAcceptOnceFileListFilter. It doesn't implement ahashCode()method, so every single new instance is different from another even if the target file is the same. For this purpose we have anSftpPersistentAcceptOnceFileListFilterwhich really compares file names and theirgetAttrs().getMTime(). See more info in docs: https://docs.spring.io/spring-integration/docs/current/reference/html/file.html#remote-persistent-flfYou said yourself "monitoring", so you probably use over there a
Files.inboundAdapter(), which really may be configured with the mentionedAcceptOnceFileListFilter.