From 8bfb5d248f8746f3be81b9cc80d99e2b1beb9e5f Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 27 Feb 2025 10:59:20 -0500 Subject: [PATCH] GH-9869: Introduce `AbstractRecentFileListFilter` strategy Fixes: https://github.com/spring-projects/spring-integration/issues/9869 Currently, FileListFilters on the last modified attribute of a file are limited to the use case of discarding files that are too young. It would be great to have a filter implementation which would accept files which are not old enough. * Implement `AbstractRecentFileListFilter` for all the supported file protocols --- .../filters/AbstractRecentFileListFilter.java | 81 +++++++++++++++++++ .../file/filters/RecentFileListFilter.java | 44 ++++++++++ .../filters/RecentFileListFilterTests.java | 56 +++++++++++++ .../ftp/filters/FtpRecentFileListFilter.java | 48 +++++++++++ .../filters/FtpRecentFileListFilterTests.java | 57 +++++++++++++ .../filters/SftpRecentFileListFilter.java | 48 +++++++++++ .../SftpRecentFileListFilterTests.java | 59 ++++++++++++++ .../smb/filters/SmbRecentFileListFilter.java | 48 +++++++++++ .../filters/SmbRecentFileListFilterTests.java | 56 +++++++++++++ .../modules/ROOT/pages/file/reading.adoc | 7 +- .../modules/ROOT/pages/ftp/inbound.adoc | 2 + .../modules/ROOT/pages/sftp/inbound.adoc | 2 + .../antora/modules/ROOT/pages/smb.adoc | 2 + .../antora/modules/ROOT/pages/whats-new.adoc | 9 ++- 14 files changed, 517 insertions(+), 2 deletions(-) create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/filters/AbstractRecentFileListFilter.java create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/filters/RecentFileListFilter.java create mode 100644 spring-integration-file/src/test/java/org/springframework/integration/file/filters/RecentFileListFilterTests.java create mode 100644 spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilter.java create mode 100644 spring-integration-ftp/src/test/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilterTests.java create mode 100644 spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilter.java create mode 100644 spring-integration-sftp/src/test/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilterTests.java create mode 100644 spring-integration-smb/src/main/java/org/springframework/integration/smb/filters/SmbRecentFileListFilter.java create mode 100644 spring-integration-smb/src/test/java/org/springframework/integration/smb/filters/SmbRecentFileListFilterTests.java diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/filters/AbstractRecentFileListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/AbstractRecentFileListFilter.java new file mode 100644 index 0000000000..806af36adf --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/AbstractRecentFileListFilter.java @@ -0,0 +1,81 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.file.filters; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link FileListFilter} to accept only files which are recent according to provided {@code age}: + * the {@code lastModified} of the file is more than the age in comparison with the current time. + * In other words, accept those files which are not old enough yet. + * + * @param The type that will be filtered. + * + * @author Artem Bilan + * + * @since 6.5 + */ +public abstract class AbstractRecentFileListFilter implements FileListFilter { + + protected static final long ONE_SECOND = 1000; + + private final Duration age; + + /** + * Construct an instance with default age as 1 day. + */ + public AbstractRecentFileListFilter() { + this(Duration.ofDays(1)); + } + + public AbstractRecentFileListFilter(Duration age) { + this.age = age; + } + + @Override + public boolean supportsSingleFileFiltering() { + return true; + } + + @Override + public List filterFiles(F[] files) { + List list = new ArrayList<>(); + Instant now = Instant.now(); + for (F file : files) { + if (!fileIsAged(file, now)) { + list.add(file); + } + } + + return list; + } + + @Override + public boolean accept(F file) { + return !fileIsAged(file, Instant.now()); + } + + protected boolean fileIsAged(F file, Instant now) { + return getLastModified(file).plus(this.age).isBefore(now); + } + + protected abstract Instant getLastModified(F remoteFile); + +} diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/filters/RecentFileListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/RecentFileListFilter.java new file mode 100644 index 0000000000..0ea2ba009d --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/filters/RecentFileListFilter.java @@ -0,0 +1,44 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.file.filters; + +import java.io.File; +import java.time.Duration; +import java.time.Instant; + +/** + * The {@link AbstractRecentFileListFilter} implementation for local file system. + * + * @author Artem Bilan + * + * @since 6.5 + */ +public class RecentFileListFilter extends AbstractRecentFileListFilter { + + public RecentFileListFilter() { + } + + public RecentFileListFilter(Duration age) { + super(age); + } + + @Override + protected Instant getLastModified(File file) { + return Instant.ofEpochSecond(file.lastModified() / ONE_SECOND); + } + +} diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/filters/RecentFileListFilterTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/filters/RecentFileListFilterTests.java new file mode 100644 index 0000000000..fbcc504a87 --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/filters/RecentFileListFilterTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.file.filters; + +import java.io.File; +import java.io.FileOutputStream; +import java.time.Duration; +import java.time.Instant; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Artem Bilan + * + * @since 6.5 + * + */ +public class RecentFileListFilterTests { + + @TempDir + public File folder; + + @Test + public void testAge() throws Exception { + RecentFileListFilter filter = new RecentFileListFilter(Duration.ofHours(20)); + File testFile = new File(folder, "test.tmp"); + FileOutputStream fileOutputStream = new FileOutputStream(testFile); + fileOutputStream.write("x".getBytes()); + fileOutputStream.close(); + assertThat(filter.filterFiles(new File[] {testFile})).hasSize(1); + assertThat(filter.accept(testFile)).isTrue(); + + testFile.setLastModified(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()); + + assertThat(filter.filterFiles(new File[] {testFile})).hasSize(0); + assertThat(filter.accept(testFile)).isFalse(); + } + +} diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilter.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilter.java new file mode 100644 index 0000000000..24e9dc8145 --- /dev/null +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.ftp.filters; + +import java.time.Duration; +import java.time.Instant; + +import org.apache.commons.net.ftp.FTPFile; + +import org.springframework.integration.file.filters.AbstractRecentFileListFilter; + +/** + * The {@link AbstractRecentFileListFilter} implementation for FTP protocol. + * + * @author Artem Bilan + * + * @since 6.5 + */ +public class FtpRecentFileListFilter extends AbstractRecentFileListFilter { + + public FtpRecentFileListFilter() { + super(); + } + + public FtpRecentFileListFilter(Duration age) { + super(age); + } + + @Override + protected Instant getLastModified(FTPFile remoteFile) { + return remoteFile.getTimestampInstant(); + } + +} diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilterTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilterTests.java new file mode 100644 index 0000000000..ad4e68fb4a --- /dev/null +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/filters/FtpRecentFileListFilterTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.ftp.filters; + +import java.time.Duration; +import java.util.Calendar; + +import org.apache.commons.net.ftp.FTPFile; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Artem Bilan + * + * @since 6.5 + */ +public class FtpRecentFileListFilterTests { + + @Test + public void testAge() { + FtpRecentFileListFilter filter = new FtpRecentFileListFilter(Duration.ofHours(20)); + FTPFile ftpFile1 = new FTPFile(); + ftpFile1.setName("foo"); + ftpFile1.setTimestamp(Calendar.getInstance()); + FTPFile ftpFile2 = new FTPFile(); + ftpFile2.setName("bar"); + ftpFile2.setTimestamp(Calendar.getInstance()); + FTPFile[] files = new FTPFile[] {ftpFile1, ftpFile2}; + assertThat(filter.filterFiles(files)).hasSize(2); + assertThat(filter.accept(ftpFile1)).isTrue(); + assertThat(filter.accept(ftpFile2)).isTrue(); + + // Make a file as of yesterday's + final Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DATE, -1); + ftpFile2.setTimestamp(calendar); + + assertThat(filter.filterFiles(files)).hasSize(1); + assertThat(filter.accept(ftpFile1)).isTrue(); + } + +} diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilter.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilter.java new file mode 100644 index 0000000000..71c6b46f8b --- /dev/null +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.sftp.filters; + +import java.time.Duration; +import java.time.Instant; + +import org.apache.sshd.sftp.client.SftpClient; + +import org.springframework.integration.file.filters.AbstractRecentFileListFilter; + +/** + * The {@link AbstractRecentFileListFilter} implementation for SFTP protocol. + * + * @author Artem Bilan + * + * @since 6.5 + */ +public class SftpRecentFileListFilter extends AbstractRecentFileListFilter { + + public SftpRecentFileListFilter() { + super(); + } + + public SftpRecentFileListFilter(Duration age) { + super(age); + } + + @Override + protected Instant getLastModified(SftpClient.DirEntry remoteFile) { + return remoteFile.getAttributes().getModifyTime().toInstant(); + } + +} diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilterTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilterTests.java new file mode 100644 index 0000000000..aaae00eef2 --- /dev/null +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/filters/SftpRecentFileListFilterTests.java @@ -0,0 +1,59 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.sftp.filters; + +import java.nio.file.attribute.FileTime; +import java.time.Duration; +import java.time.Instant; + +import org.apache.sshd.sftp.client.SftpClient; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Artem Bilan + * + * @since 6.5 + */ +public class SftpRecentFileListFilterTests { + + @Test + public void testAge() { + SftpRecentFileListFilter filter = new SftpRecentFileListFilter(Duration.ofHours(20)); + SftpClient.Attributes attributes1 = new SftpClient.Attributes(); + attributes1.setModifyTime(FileTime.from(Instant.now())); + SftpClient.Attributes attributes2 = new SftpClient.Attributes(); + attributes2.setModifyTime(FileTime.from(Instant.now())); + + SftpClient.DirEntry sftpFile1 = new SftpClient.DirEntry("foo", "foo", attributes1); + SftpClient.DirEntry sftpFile2 = new SftpClient.DirEntry("bar", "bar", attributes2); + + SftpClient.DirEntry[] files = new SftpClient.DirEntry[] {sftpFile1, sftpFile2}; + + assertThat(filter.filterFiles(files)).hasSize(2); + assertThat(filter.accept(sftpFile1)).isTrue(); + assertThat(filter.accept(sftpFile2)).isTrue(); + + FileTime fileTime = FileTime.from(Instant.now().minus(Duration.ofDays(1))); + sftpFile2.getAttributes().setModifyTime(fileTime); + assertThat(filter.filterFiles(files)).hasSize(1); + assertThat(filter.accept(sftpFile1)).isTrue(); + assertThat(filter.accept(sftpFile2)).isFalse(); + } + +} diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/filters/SmbRecentFileListFilter.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/filters/SmbRecentFileListFilter.java new file mode 100644 index 0000000000..abe895487e --- /dev/null +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/filters/SmbRecentFileListFilter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.smb.filters; + +import java.time.Duration; +import java.time.Instant; + +import jcifs.smb.SmbFile; + +import org.springframework.integration.file.filters.AbstractRecentFileListFilter; + +/** + * The {@link AbstractRecentFileListFilter} implementation for SMB protocol. + * + * @author Artem Bilan + * + * @since 6.2 + */ +public class SmbRecentFileListFilter extends AbstractRecentFileListFilter { + + public SmbRecentFileListFilter() { + super(); + } + + public SmbRecentFileListFilter(Duration age) { + super(age); + } + + @Override + protected Instant getLastModified(SmbFile remoteFile) { + return Instant.ofEpochSecond(remoteFile.getLastModified() / ONE_SECOND); + } + +} diff --git a/spring-integration-smb/src/test/java/org/springframework/integration/smb/filters/SmbRecentFileListFilterTests.java b/spring-integration-smb/src/test/java/org/springframework/integration/smb/filters/SmbRecentFileListFilterTests.java new file mode 100644 index 0000000000..09ebb7eee3 --- /dev/null +++ b/spring-integration-smb/src/test/java/org/springframework/integration/smb/filters/SmbRecentFileListFilterTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.smb.filters; + +import java.time.Duration; +import java.time.Instant; + +import jcifs.smb.SmbFile; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Artem Bilan + * + * @since 6.5 + */ +public class SmbRecentFileListFilterTests { + + @Test + public void testAge() { + SmbRecentFileListFilter filter = new SmbRecentFileListFilter(Duration.ofHours(20)); + SmbFile smbFile1 = mock(); + when(smbFile1.getLastModified()).thenReturn(System.currentTimeMillis()); + SmbFile smbFile2 = mock(); + when(smbFile2.getLastModified()).thenReturn(System.currentTimeMillis()); + SmbFile smbFile3 = mock(); + + when(smbFile3.getLastModified()) + .thenReturn(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()); + + SmbFile[] files = new SmbFile[] {smbFile1, smbFile2, smbFile3}; + + assertThat(filter.filterFiles(files)).hasSize(2); + assertThat(filter.accept(smbFile1)).isTrue(); + assertThat(filter.accept(smbFile2)).isTrue(); + assertThat(filter.accept(smbFile3)).isFalse(); + } + +} diff --git a/src/reference/antora/modules/ROOT/pages/file/reading.adoc b/src/reference/antora/modules/ROOT/pages/file/reading.adoc index 4178345c3d..9fdfd42c8f 100644 --- a/src/reference/antora/modules/ROOT/pages/file/reading.adoc +++ b/src/reference/antora/modules/ROOT/pages/file/reading.adoc @@ -138,7 +138,12 @@ The `CompositeFileListFilter` also implements a `DiscardAwareFileListFilter` and NOTE: Since `CompositeFileListFilter` matches the files against all delegates, the `discardCallback` may be called several times for the same file. Starting with version 5.1, the `FileReadingMessageSource` doesn't check a directory for existence and doesn't create it until its `start()` is called (typically via wrapping `SourcePollingChannelAdapter`). -Previously, there was no simple way to prevent an operation system permissions error when referencing the directory, for example from tests, or when permissions are applied later. +Previously, there was no simple way to prevent the operating system permissions error when referencing the directory, for example from tests, or when permissions are applied later. + +In opposition to the `LastModifiedFileListFilter`, a `RecentFileListFilter` strategy has been introduced starting version 6.5. +It is an extension for local file system of the `AbstractRecentFileListFilter`. +By default, it accepts files which are not older than 1 day. +See its other implementations for respective remote file protocol. [[message-headers]] == Message Headers diff --git a/src/reference/antora/modules/ROOT/pages/ftp/inbound.adoc b/src/reference/antora/modules/ROOT/pages/ftp/inbound.adoc index e7202e8d79..c1473119fd 100644 --- a/src/reference/antora/modules/ROOT/pages/ftp/inbound.adoc +++ b/src/reference/antora/modules/ROOT/pages/ftp/inbound.adoc @@ -103,6 +103,8 @@ This filter can be configured with an `age` property so that only files older th The age defaults to 60 seconds, but you should choose an age that is large enough to avoid picking up a file early (due to, say, network glitches). Look into its Javadoc for more information. +In contrast, starting with version 6.5, an `FtpRecentFileListFilter` has been introduced to accept only those files which are not older than provided `age`. + [[more-on-file-filtering-and-incomplete-files]] == More on File Filtering and Incomplete Files diff --git a/src/reference/antora/modules/ROOT/pages/sftp/inbound.adoc b/src/reference/antora/modules/ROOT/pages/sftp/inbound.adoc index 7df3b53234..df316bc00b 100644 --- a/src/reference/antora/modules/ROOT/pages/sftp/inbound.adoc +++ b/src/reference/antora/modules/ROOT/pages/sftp/inbound.adoc @@ -100,6 +100,8 @@ This filter can be configured with an `age` property so that only files older th The age defaults to 60 seconds, but you should choose an age that is large enough to avoid picking up a file early (due to, say, network glitches). Look into its Javadoc for more information. +In contrast, starting with version 6.5, an `SftpRecentFileListFilter` has been introduced to accept only those files which are not older than provided `age`. + [[more-on-file-filtering-and-large-files]] == More on File Filtering and Large Files diff --git a/src/reference/antora/modules/ROOT/pages/smb.adoc b/src/reference/antora/modules/ROOT/pages/smb.adoc index 8f1245c934..6b85233937 100644 --- a/src/reference/antora/modules/ROOT/pages/smb.adoc +++ b/src/reference/antora/modules/ROOT/pages/smb.adoc @@ -162,6 +162,8 @@ This filter can be configured with an `age` property so that only files older th The age defaults to 60 seconds, but you should choose an age that is large enough to avoid picking up a file early (due to, say, network glitches. Look into its Javadoc for more information. +In contrast, starting with version 6.5, an `SmbRecentFileListFilter` has been introduced to accept only those files which are not older than provided `age`. + [[configuring-with-the-java-dsl]] === Configuring with the Java DSL diff --git a/src/reference/antora/modules/ROOT/pages/whats-new.adoc b/src/reference/antora/modules/ROOT/pages/whats-new.adoc index 73e5e6838f..80118e6f3e 100644 --- a/src/reference/antora/modules/ROOT/pages/whats-new.adoc +++ b/src/reference/antora/modules/ROOT/pages/whats-new.adoc @@ -61,4 +61,11 @@ See xref:mqtt.adoc[MQTT Support] for more information. The `KafkaMessageSource` and `KafkaMessageDrivenChannelAdapter` now generate `MessageHeaders.ID` and `MessageHeaders.TIMESTAMP` headers by default as the rest of Spring Integration channel adapters. The behavior can be restored to the previous with injection of the `MessagingMessageConverter` with default settings. -See xref:kafka.adoc[Apache Kafka Support] for more information. \ No newline at end of file +See xref:kafka.adoc[Apache Kafka Support] for more information. + +[[x6.5-file-filter-changes]] +== The Recent File Filter Support + +The `AbstractRecentFileListFilter` strategy has been introduced to accept only those files which are not old enough according to the provided `age`. +The respective implementations are provided: `RecentFileListFilter`, `FtpRecentFileListFilter`, `SftpRecentFileListFilter` and `SmbRecentFileListFilter`. +See xref:file/reading.adoc[Reading Files] for more information. \ No newline at end of file