diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterFactoryBean.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterFactoryBean.java index f8feb79891..a46873b996 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterFactoryBean.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterFactoryBean.java @@ -35,6 +35,7 @@ import org.springframework.util.StringUtils; /** * @author Gary Russell * @author Artem Bilan + * @author Ali Shahbour * @since 3.0 * */ @@ -43,6 +44,8 @@ public class FileTailInboundChannelAdapterFactoryBean extends AbstractFactoryBea private volatile String nativeOptions; + private volatile boolean enableStatusReader = true; + private volatile File file; private volatile TaskExecutor taskExecutor; @@ -77,6 +80,16 @@ public class FileTailInboundChannelAdapterFactoryBean extends AbstractFactoryBea } } + /** + * If false, thread for capturing stderr will not be started + * and stderr output will be ignored + * @param enableStatusReader true or false + * @since 4.3.6 + */ + public void setEnableStatusReader(boolean enableStatusReader) { + this.enableStatusReader = enableStatusReader; + } + public void setFile(File file) { this.file = file; } @@ -180,6 +193,7 @@ public class FileTailInboundChannelAdapterFactoryBean extends AbstractFactoryBea FileTailingMessageProducerSupport adapter; if (this.delay == null && this.end == null && this.reopen == null) { adapter = new OSDelegatingFileTailingMessageProducer(); + ((OSDelegatingFileTailingMessageProducer) adapter).setEnableStatusReader(this.enableStatusReader); if (this.nativeOptions != null) { ((OSDelegatingFileTailingMessageProducer) adapter).setOptions(this.nativeOptions); } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParser.java index fb430ae0c1..4d0b93f332 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParser.java @@ -28,6 +28,7 @@ import org.springframework.util.StringUtils; /** * @author Gary Russell * @author Artem Bilan + * @author Ali Shahbour * @since 3.0 * */ @@ -41,6 +42,7 @@ public class FileTailInboundChannelAdapterParser extends AbstractChannelAdapterP builder.addPropertyReference("outputChannel", channelName); } IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "native-options"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "enable-status-reader"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "file"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "task-executor"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "task-scheduler"); diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/tail/OSDelegatingFileTailingMessageProducer.java b/spring-integration-file/src/main/java/org/springframework/integration/file/tail/OSDelegatingFileTailingMessageProducer.java index 8dd74c5f86..1c26e18c7c 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/tail/OSDelegatingFileTailingMessageProducer.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/tail/OSDelegatingFileTailingMessageProducer.java @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * * @author Gary Russell * @author Gavin Gray + * @author Ali Shahbour * @since 3.0 * */ @@ -46,6 +47,8 @@ public class OSDelegatingFileTailingMessageProducer extends FileTailingMessagePr private volatile String command = "ADAPTER_NOT_INITIALIZED"; + private volatile boolean enableStatusReader = true; + private volatile BufferedReader reader; private volatile TaskScheduler scheduler; @@ -59,6 +62,16 @@ public class OSDelegatingFileTailingMessageProducer extends FileTailingMessagePr } } + /** + * If false, thread for capturing stderr will not be started + * and stderr output will be ignored + * @param enableStatusReader true or false + * @since 4.3.6 + */ + public void setEnableStatusReader(boolean enableStatusReader) { + this.enableStatusReader = enableStatusReader; + } + public String getCommand() { return this.command; } @@ -114,7 +127,9 @@ public class OSDelegatingFileTailingMessageProducer extends FileTailingMessagePr BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); this.process = process; this.startProcessMonitor(); - this.startStatusReader(); + if (this.enableStatusReader) { + startStatusReader(); + } this.reader = reader; this.getTaskExecutor().execute(this); } diff --git a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-5.0.xsd b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-5.0.xsd index 1d90625b6d..15033ab4b4 100644 --- a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-5.0.xsd +++ b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-5.0.xsd @@ -234,6 +234,17 @@ Only files matching this regular expression will be picked up by this adapter. + + + + Configure the adapter to either start a thread for capturing stderr or not. + Default: True + + + + + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests-context.xml index d560e34ad6..acce911261 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests-context.xml +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests-context.xml @@ -28,6 +28,7 @@ native-options="-F -n 6" task-executor="exec" task-scheduler="sched" + enable-status-reader="false" file-delay="456" file="/tmp/foo" auto-startup="true" diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests.java index 29c2bcd7a9..9d044b8982 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileTailInboundChannelAdapterParserTests.java @@ -38,15 +38,18 @@ import org.springframework.messaging.MessageChannel; import org.springframework.scheduling.TaskScheduler; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.annotation.DirtiesContext; /** * @author Gary Russell * @author Artem Bilan * @author Gavin Gray + * @author Ali Shahbour * @since 3.0 */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) +@DirtiesContext public class FileTailInboundChannelAdapterParserTests { @Autowired @Qualifier("default") @@ -78,6 +81,7 @@ public class FileTailInboundChannelAdapterParserTests { assertEquals("tail -F -n 0 " + fileName, TestUtils.getPropertyValue(defaultAdapter, "command")); assertSame(exec, TestUtils.getPropertyValue(defaultAdapter, "taskExecutor")); assertTrue(TestUtils.getPropertyValue(defaultAdapter, "autoStartup", Boolean.class)); + assertTrue(TestUtils.getPropertyValue(defaultAdapter, "enableStatusReader", Boolean.class)); assertEquals(123, TestUtils.getPropertyValue(defaultAdapter, "phase")); assertSame(this.tailErrorChannel, TestUtils.getPropertyValue(defaultAdapter, "errorChannel")); this.defaultAdapter.stop(); @@ -95,6 +99,7 @@ public class FileTailInboundChannelAdapterParserTests { assertSame(exec, TestUtils.getPropertyValue(nativeAdapter, "taskExecutor")); assertSame(sched, TestUtils.getPropertyValue(nativeAdapter, "taskScheduler")); assertTrue(TestUtils.getPropertyValue(nativeAdapter, "autoStartup", Boolean.class)); + assertFalse(TestUtils.getPropertyValue(nativeAdapter, "enableStatusReader", Boolean.class)); assertEquals(123, TestUtils.getPropertyValue(nativeAdapter, "phase")); assertEquals(456L, TestUtils.getPropertyValue(nativeAdapter, "tailAttemptsDelay")); } diff --git a/src/reference/asciidoc/file.adoc b/src/reference/asciidoc/file.adoc index edc1dad53c..2202b66bc2 100644 --- a/src/reference/asciidoc/file.adoc +++ b/src/reference/asciidoc/file.adoc @@ -446,6 +446,18 @@ This creates a native adapter with default '-F -n 0' options (follow the file na This creates a native adapter with '-F -n +0' options (follow the file name, emitting all existing lines). If the tail command fails (on some platforms, a missing file causes the `tail` to fail, even with `-F` specified), the command will be retried every 10 seconds. +[source,xml] +---- + +---- + +By default native adapter capture from standard output and send them as messages and from standard error to raise events. +Starting with _version 4.3.6_, you can discard the standard error events by setting the `enable-status-reader` to `false`. + [source,xml] ----