INT-4147: Fix NPE in the FileReadingMessageSource

JIRA: https://jira.spring.io/browse/INT-4147

By default `FileReadingMessageSource` is created without `filter`, at the same time internal `WatchServiceDirectoryScanner` is supplied with default `filter` by its `DefaultDirectoryScanner` super class.
A `DELETE` watch event condition around `FileReadingMessageSource.this.filter` is wrong, because it is `null` by default. Therefore `DELETE` events never succeed

* Modify `FileInboundTransactionTests` to accept `DELETE` watch event as well and verify that `ResettableFileListFilter.remove(File)` is performed
* Call newly created getter for `DefaultDirectoryScanner.filter` in the `WatchServiceDirectoryScanner` to assert against supplied `filter`

Polishing

**Cherry-pick to 4.3.x**
This commit is contained in:
Artem Bilan
2016-10-25 10:09:34 -04:00
committed by Gary Russell
parent ee848e9ecf
commit 8c95f001da
4 changed files with 27 additions and 5 deletions

View File

@@ -62,11 +62,19 @@ public class DefaultDirectoryScanner implements DirectoryScanner {
this.filter = filter;
}
protected FileListFilter<File> getFilter() {
return this.filter;
}
@Override
public final void setLocker(FileLocker locker) {
this.locker = locker;
}
protected FileLocker getLocker() {
return this.locker;
}
/**
* This class takes the minimal implementation and merely delegates to the locker if set.
* @param file the file to try to claim.

View File

@@ -490,8 +490,8 @@ public class FileReadingMessageSource extends IntegrationObjectSupport implement
}
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
if (FileReadingMessageSource.this.filter instanceof ResettableFileListFilter) {
((ResettableFileListFilter<File>) FileReadingMessageSource.this.filter).remove(file);
if (getFilter() != null && getFilter() instanceof ResettableFileListFilter) {
((ResettableFileListFilter<File>) getFilter()).remove(file);
}
boolean fileRemoved = files.remove(file);
if (fileRemoved && logger.isDebugEnabled()) {

View File

@@ -14,7 +14,8 @@
<int-file:inbound-channel-adapter id="pseudoTx"
channel="input" auto-startup="false"
directory="#{T (org.springframework.integration.file.FileInboundTransactionTests).tmpDir.root}/si-test1"
use-watch-service="true">
use-watch-service="true"
watch-events="CREATE,DELETE">
<int:poller fixed-rate="500">
<int:transactional synchronization-factory="syncFactoryA"/>
</int:poller>

View File

@@ -22,6 +22,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import java.io.File;
import java.util.concurrent.CountDownLatch;
@@ -32,8 +34,10 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.file.filters.ResettableFileListFilter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
@@ -84,6 +88,16 @@ public class FileInboundTransactionTests {
@Test
public void testNoTx() throws Exception {
Object scanner = TestUtils.getPropertyValue(pseudoTx.getMessageSource(), "scanner");
assertThat(scanner.getClass().getName(), containsString("FileReadingMessageSource$WatchServiceDirectoryScanner"));
@SuppressWarnings("unchecked")
ResettableFileListFilter<File> fileListFilter =
spy(TestUtils.getPropertyValue(scanner, "filter", ResettableFileListFilter.class));
new DirectFieldAccessor(scanner).setPropertyValue("filter", fileListFilter);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean crash = new AtomicBoolean();
input.subscribe(message -> {
@@ -110,8 +124,7 @@ public class FileInboundTransactionTests {
assertFalse(transactionManager.getCommitted());
assertFalse(transactionManager.getRolledBack());
Object scanner = TestUtils.getPropertyValue(pseudoTx.getMessageSource(), "scanner");
assertThat(scanner.getClass().getName(), containsString("FileReadingMessageSource$WatchServiceDirectoryScanner"));
verify(fileListFilter).remove(new File(tmpDir.getRoot(), "si-test1/foo"));
}
@Test