Skip to content

Loading…

INT-2855 File Tailing Inbound Channel Adapter #802

Closed
wants to merge 7 commits into from

4 participants

@garyrussell
Spring member

Two implementations:

  • native 'tail' command (e.g. tail -F -n 0 /foo/bar)
  • Apache commons-io Tailer
@markfisher markfisher commented on an outdated diff
...ile/tail/ApacheCommonsFileTailingMessageProducer.java
((36 lines not shown))
+
+ public void setPollingDelay(long pollingDelay) {
+ this.pollingDelay = pollingDelay;
+ }
+
+ public void setMissingFileDelay(long missingFileDelay) {
+ this.missingFileDelay = missingFileDelay;
+ }
+
+ @Override
+ public String getComponentType() {
+ return super.getComponentType() + " (Apache)";
+ }
+
+ @Override
+ protected void onInit() {
@markfisher Spring member

I guess we can remove this onInit() method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...tion/file/tail/FileTailingMessageProducerSupport.java
((32 lines not shown))
+ * Base class for file tailing inbound adapters.
+ *
+ * @author Gary Russell
+ * @since 3.0
+ *
+ */
+public abstract class FileTailingMessageProducerSupport extends MessageProducerSupport
+ implements ApplicationEventPublisherAware {
+
+ private volatile File file;
+
+ private volatile ApplicationEventPublisher eventPublisher;
+
+ private volatile TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
+
+ private volatile CountDownLatch started;
@markfisher Spring member

should this be initialized on this line?... looks like possibility of NPE in the hasStarted() method below.

@artembilan Spring member

Why it is CountDownLatch at all? I don't see any await call in this class and even in the inheritors...
You use it in the test, but...

@garyrussell Spring member

Yeah - I just added it for the test case - I hate using heuristics in tests :smile:

I can remove it and come up with something else if you prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...file/tail/OSDelegatingFileTailingMessageProducer.java
((96 lines not shown))
+ try {
+ result = process.waitFor();
+ if (logger.isInfoEnabled()) {
+ logger.info("tail process terminated with value " + result);
+ }
+ }
+ catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ finally {
+ if (process != null) {
+ process.destroy();
+ process = null;
+ }
+ }
+ if (isRunning()) {
@markfisher Spring member

do we want this to continue even if the thread was interrupted above?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...file/tail/OSDelegatingFileTailingMessageProducer.java
((127 lines not shown))
+ while ((statusMessage = errorReader.readLine()) != null) {
+ publish(statusMessage);
+ if (logger.isTraceEnabled()) {
+ logger.trace(statusMessage);
+ }
+ }
+ }
+ catch (IOException e) {
+ logger.error("Exception on tail error reader", e);
+ }
+ finally {
+ try {
+ errorReader.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
@markfisher Spring member

should this be a logger call instead of printStackTrace?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...file/tail/OSDelegatingFileTailingMessageProducer.java
((71 lines not shown))
+ if (this.process != null) {
+ this.process.destroy();
+ this.process = null;
+ }
+ }
+
+ private void runExec() {
+ try {
+ this.process = Runtime.getRuntime().exec(this.command);
+ this.reader = new BufferedReader(new InputStreamReader(this.process.getInputStream()));
+ this.getTaskExecutor().execute(this);
+ this.startStatusReader();
+ this.startProcessMonitor();
+ }
+ catch (IOException e) {
+ throw new MessagingException("Failed to exec tail command: '" + this.options + "'", e);
@markfisher Spring member

should the message include "command with options:" + this.options ?

@garyrussell Spring member

By this time, command now includes the options and filename; just need to change options -> command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...tegration/file/config/spring-integration-file-3.0.xsd
((29 lines not shown))
+ ]]></xsd:documentation>
+ <xsd:appinfo>
+ <tool:annotation kind="ref">
+ <tool:expected-type type="org.springframework.integration.MessageChannel"/>
+ </tool:annotation>
+ </xsd:appinfo>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="native-options" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation>
+ Configures the adapter to exec 'tail' with these options (appended by the file name). This
+ will likely be the most efficient implementation on operating systems that
+ support a 'tail' command. Example: "-F -n 0" (follow the filename and emit no
+ existing lines). When this attribute is not
+ specified, the Apache commons-io 'Tailer' class is used instead.
@markfisher Spring member

given that "-F -n 0" is the default value for this.options in the OsDelegating... class above, I'm wondering if there's a better way to be able to simply designate "native" with those defaults. I know having a boolean flag and then also providing this attribute that would only make sense if that boolean had a particular value is not ideal... any other ideas though?

@garyrussell Spring member

We could flip it over - default to OSDelegating... unless one of the Apache attributes is provided (delay, file-delay).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...tegration/file/config/spring-integration-file-3.0.xsd
((57 lines not shown))
+ <xsd:documentation>
+ A reference to a TaskExecutor; default is a SimpleAsyncTaskExecutor; the
+ native adapter uses two threads - one for stdout the other for stderr.
+ </xsd:documentation>
+ <xsd:appinfo>
+ <tool:annotation kind="ref">
+ <tool:expected-type type="org.springframework.core.task.TaskExecutor"/>
+ </tool:annotation>
+ </xsd:appinfo>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="delay" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation>
+ Does not apply to the native adapter - the delay in milliseconds between polls when no new
+ data was detected in the file. Defailt 1000.
@markfisher Spring member

typo: Defailt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...tegration/file/config/spring-integration-file-3.0.xsd
((65 lines not shown))
+ </xsd:appinfo>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="delay" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation>
+ Does not apply to the native adapter - the delay in milliseconds between polls when no new
+ data was detected in the file. Defailt 1000.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="file-delay" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation>
+ Does not apply to the native adapter - the delay in milliseconds between attempts to open
+ the file when no file was found. Defailt 5000.
@markfisher Spring member

typo: Defailt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@markfisher markfisher commented on an outdated diff
...ration/file/tail/FileTailingMessageProducerTests.java
((65 lines not shown))
+ @Test
+ public void testApache() throws Exception {
+ ApacheCommonsFileTailingMessageProducer adapter = new ApacheCommonsFileTailingMessageProducer();
+ adapter.setMissingFileDelay(500);
+ adapter.setPollingDelay(100);
+ testGuts(adapter);
+ }
+
+ private void testGuts(FileTailingMessageProducerSupport adapter) throws InterruptedException,
+ FileNotFoundException, IOException {
+ final List<FileTailingEvent> events = new ArrayList<FileTailingEvent>();
+ adapter.setApplicationEventPublisher(new ApplicationEventPublisher() {
+ @Override
+ public void publishEvent(ApplicationEvent event) {
+ FileTailingEvent tailEvent = (FileTailingEvent) event;
+ System.err.println(tailEvent);
@markfisher Spring member

should probably remove the System.err

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@artembilan artembilan commented on the diff
...tion/file/tail/FileTailingMessageProducerSupport.java
((83 lines not shown))
+ }
+
+ protected void send(String line) {
+ Message<?> message = MessageBuilder.withPayload(line)
+ .setHeader(FileHeaders.FILENAME, this.file.getAbsolutePath())
+ .build();
+ super.sendMessage(message);
+ }
+
+ protected void publish(String message) {
+ if (this.eventPublisher != null) {
+ FileTailingEvent event = new FileTailingEvent(this, message, this.file);
+ this.eventPublisher.publishEvent(event);
+ }
+ else {
+ logger.info("No publisher for event:" + message);
@artembilan Spring member

Whitespace after colon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@artembilan artembilan commented on an outdated diff
...file/tail/OSDelegatingFileTailingMessageProducer.java
((44 lines not shown))
+
+ public void setOptions(String options) {
+ this.options = options;
+ }
+
+ @Override
+ public String getComponentType() {
+ return super.getComponentType() + " (native)";
+ }
+
+ @Override
+ protected void onInit() {
+ Assert.notNull(getFile(), "File cannot be null");
+ super.onInit();
+ String command = "tail";
+ this.command = command + " " + this.options + " " + this.getFile().getAbsolutePath();
@artembilan Spring member

There is no a setter for command, so this line has to be simplified and there si no NPE check for options.

@garyrussell Spring member

Thanks, this was a carryover from when I allowed them to inject the full command; we decided that might not be a good idea ("rm *") :smile:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell
Spring member

Pushed first polishing commit

@artembilan artembilan commented on an outdated diff
...tion/file/tail/FileTailingMessageProducerSupport.java
((33 lines not shown))
+ * Base class for file tailing inbound adapters.
+ *
+ * @author Gary Russell
+ * @since 3.0
+ *
+ */
+public abstract class FileTailingMessageProducerSupport extends MessageProducerSupport
+ implements ApplicationEventPublisherAware {
+
+ private volatile File file;
+
+ private volatile ApplicationEventPublisher eventPublisher;
+
+ private volatile TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
+
+ private volatile CountDownLatch started = new CountDownLatch(1);
@artembilan Spring member

Gary, I would have insisted to change it to something more usefull in logic of this class.
Spring code has been always an exemplar for me. It taught me how to use patterns, build KISS & DRY solutions. And, of course, Spring contains a lot of ready-made algorithms.
In this case end-developers will be a bit confused seeing this code and it takes some time to understand what's going on.
From other side, we can live with it, a fortiori we develop framework, where no need much Java code :smile:
BTW, the main reason why I've looked at this PR: "how can I 'tail' on Windows?" But I see noisy CountDownLatch...

@garyrussell Spring member

OK; I'm convinced :smile:

I'll remove it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell
Spring member

Pushed - removed the CountDownLatch that was only used by the test cases.

However, in doing so, I found a race condition in the OSDFTMP where the main thread could NPE because the reader was not yet initialized so I added a CDL to solve that.

@artembilan artembilan commented on an outdated diff
...file/tail/OSDelegatingFileTailingMessageProducer.java
((83 lines not shown))
+ private void destroyProcess() {
+ if (this.process != null) {
+ this.process.destroy();
+ this.process = null;
+ }
+ }
+
+ /**
+ * Exec the native tail process.
+ */
+ private void runExec() {
+ try {
+ this.readerInitialized = new CountDownLatch(1);
+ Process process = Runtime.getRuntime().exec(this.command);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ this.getTaskExecutor().execute(this);
@artembilan Spring member

But maybe instead of CDL move this line to the end of this method?..

@garyrussell Spring member

oops - of course.

Hey - I thought you were on vaca.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell
Spring member

Pushed (not enough coffee).

@ghillert ghillert commented on an outdated diff
...ration/file/tail/FileTailingMessageProducerTests.java
((86 lines not shown))
+ adapter.setOutputChannel(outputChannel);
+ adapter.afterPropertiesSet();
+ File file = new File(testDir, "foo");
+ File renamed = new File(testDir, "bar");
+ file.delete();
+ renamed.delete();
+ adapter.start();
+ waitForField(adapter, field);
+ FileOutputStream foo = new FileOutputStream(file);
+ for (int i = 0; i < 50; i++) {
+ foo.write(("hello" + i + "\n").getBytes());
+ }
+ foo.flush();
+ for (int i = 0; i < 50; i++) {
+ Message<?> message = outputChannel.receive(5000);
+ assertNotNull(message);
@ghillert Spring member

Maybe add an assertion message:

assertNotNull("message must not be null", message);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@ghillert
Spring member

On my Mac the test FileTailingMessageProducerTests#testOS() fails 100% of the time.

FileTailingMessageProducerTests: FileTailingEvent org.springframework.integration.file.tail.FileTailingMessageProducerSupport$FileTailingEvent[source=org.springframework.integration.file.tail.OSDelegatingFileTailingMessageProducer@6a67d193] [message=tail: /var/folders/hs/h87zy7z17qs6mcnl4hj8_dp00000gp/T/FileTailingMessageProducerTests/foo: No such file or directory, file=/var/folders/hs/h87zy7z17qs6mcnl4hj8_dp00000gp/T/FileTailingMessageProducerTests/foo]
OSDelegatingFileTailingMessageProducer: Exception on tail error reader
java.io.IOException: Stream closed

Also, what happens if somebody builds SI on Windows? Should we test (e.g. JunitRule) if tail is available?

@artembilan
Spring member

Hi, there!

what happens if somebody builds SI on Windows?

Right, Gunnar. FileTailingMessageProducerTests#testOS() is failed on Windows:
[message=tail: invalid option -- F, file=C:\Users\cleric\LOCALS~1\Temp\FileTailingMessageProducerTests\foo]
[message=Try `tail --help' for more information., file=C:\Users\cleric\LOCALS~1\Temp\FileTailingMessageProducerTests\foo]
Of course, it will be bad idea to introduce some OS-emulator, and I agree - JunitRule will be enough for similar OSs.

@ghillert ghillert commented on the diff
...ration/file/tail/FileTailingMessageProducerTests.java
((76 lines not shown))
+ adapter.setApplicationEventPublisher(new ApplicationEventPublisher() {
+ @Override
+ public void publishEvent(ApplicationEvent event) {
+ FileTailingEvent tailEvent = (FileTailingEvent) event;
+ logger.warn(event);
+ events.add(tailEvent);
+ }
+ });
+ adapter.setFile(new File(testDir, "foo"));
+ QueueChannel outputChannel = new QueueChannel();
+ adapter.setOutputChannel(outputChannel);
+ adapter.afterPropertiesSet();
+ File file = new File(testDir, "foo");
+ File renamed = new File(testDir, "bar");
+ file.delete();
+ renamed.delete();
@ghillert Spring member

Is there a timing issue? When I comment out the deletes, the test passes.

@garyrussell Spring member

I'll test on Mac - on Linux, if you tail a non-existent file, it simply emits a message on stderr and waits for the file to appear.

@garyrussell Spring member

Ugh - another :+1: for Linux Vs. Mac.

Linux tail -F waits for a non-existent file to show up (and emits status info on stderr). No such luck on OSX - #fail when no file, and no status messages.

I guess I am going to have to allow setting the file-delay attribute for the non-existent file situation (like with the Apache Tailer). And use it to relaunch the exec on a failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell
Spring member

Regarding Windows - oops - yes; we need a @ Rule so the build won't fail.

It might also be useful, if we get a reliable return result from the exec, to log it and stop the adapter, if someone tries to deploy it on Windoze.

OTOH, I am intrigued by message=Try tail --help' for more information., - does that mean newer windows now has a tail (but no -F) ?

@artembilan
Spring member

does that mean newer windows now has a tail

No, Gary, it doesn't by default, unless user hasn't installed some utility, e.g. for me it came after install Git Bash Shell.
For me FileTailingMessageProducerTests#testOS() passes in the tiny cases:

  • adapter.setOptions("--follow=name --retry -n 0");
  • if file exists
  • without rename because the Windows tail-wrapper can't retry on desriptors
  • adapter.stop(); should be invoked in the @After method: tail.exe processes are hung in the Exception case.

Anyway the @Rule has to skip OSs similar to Windows.

garyrussell added some commits
@garyrussell garyrussell INT-2855 File Tailing Inbound Channel Adapter
Two implementations:

  - native 'tail' command (e.g. tail -F -n 0 /foo/bar)
  - Apache commons-io Tailer
4da62e6
@garyrussell garyrussell INT-2855 Polishing
 - PR Reviews
 - Add what's new
a144a94
@garyrussell garyrussell INT-2855 Polishing
 - PR Comments
 - Removed CountDownLatch used only by test cases - wait for a field to be initialized instead
 - Fixed Race condition in OSDFTMP - run() referenced reader before it was available
a63746a
@garyrussell garyrussell INT-2855 Polishing
Eliminate unnecessary CountDownLatch.
e1e3f3a
@garyrussell garyrussell INT-2855 Fix for Max OSX; Other Improvements
 - Schedule Instead of Immediate Re-Run
     Mac OSX 'tail' terminates immediately when the file is
     missing.
 - Add delay when rescheduling a failed process
 - Add support for 'end' and 'reopen' options to Apache Tailer implementation
 - Clean up process destruction logic after failures
 - Add more debugging to threads
 - Add a JUnit @Rule so the OSDFTMP test doesn't fail on Windows
 - Add file path normalization so the tests pass on Windows
b34e311
@garyrussell
Spring member

Pushed...

INT-2855 Fix for Max OSX; Other Improvements

 - Schedule Instead of Immediate Re-Run
     Mac OSX 'tail' terminates immediately when the file is
     missing.
 - Add delay when rescheduling a failed process
 - Add support for 'end' and 'reopen' options to Apache Tailer implementation
 - Clean up process destruction logic after failures
 - Add more debugging to threads
 - Add a JUnit @Rule so the OSDFTMP test doesn't fail on Windows
 - Add file path normalization so the tests pass on Windows
@artembilan artembilan commented on an outdated diff
.../config/FileTailInboundChannelAdapterFactoryBean.java
((113 lines not shown))
+ @Override
+ public Class<?> getObjectType() {
+ return this.adapter == null ? FileTailingMessageProducerSupport.class : this.adapter.getClass();
+ }
+
+ @Override
+ protected FileTailingMessageProducerSupport createInstance() throws Exception {
+ FileTailingMessageProducerSupport adapter;
+ if (this.delay == null && this.end == null && this.reopen == null) {
+ adapter = new OSDelegatingFileTailingMessageProducer();
+ if (this.nativeOptions != null) {
+ ((OSDelegatingFileTailingMessageProducer) adapter).setOptions(this.nativeOptions);
+ }
+ }
+ else {
+ Assert.isNull(this.nativeOptions, "Cannot have 'delay', 'end' or 'reopen' with a native adapter");
@artembilan Spring member

What does this assert mean for ApacheCommonsFileTailingMessageProducer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@artembilan artembilan commented on an outdated diff
...ration/file/tail/FileTailingMessageProducerTests.java
((54 lines not shown))
+ private File testDir;
+
+ @Before
+ public void setup() {
+ File f = new File(tmpDir, "FileTailingMessageProducerTests");
+ f.mkdir();
+ this.testDir = f;
+ }
+
+ @Test
+ @TailAvailable
+ public void testOS() throws Exception {
+ OSDelegatingFileTailingMessageProducer adapter = new OSDelegatingFileTailingMessageProducer();
+ adapter.setOptions("-F -n 99999999");
+ testGuts(adapter, "reader");
+ }
@artembilan Spring member

Gary, this test still doesn't pass for my Windows tail-wrapper:

  • By default

    [message=tail: invalid option -- F, file=C:\Users\cleric\LOCALS~1\Temp\FileTailingMessageProducerTests\foo]

  • with --follow=name --retry -n 99999999

    org.junit.ComparisonFailure:
    Expected :hello50
    Actual :8

  • and through time:

    java.io.FileNotFoundException: C:\Users\cleric\LOCALS~1\Temp\FileTailingMessageProducerTests\foo (Access Denied)

How about just @Ignore it?
There is no guarantee, that another Windows tail-tool will work differently...

@garyrussell Spring member

I wonder if we should just add to the @Rule (if java.io.tmpdir contains :) ??

Or, I suppose we could use the same options in the test that we use in the test itself.

I'd prefer not to @Ignore it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@artembilan artembilan commented on an outdated diff
.../file/config/FileTailInboundChannelAdapterParser.java
((31 lines not shown))
+ */
+public class FileTailInboundChannelAdapterParser extends AbstractChannelAdapterParser {
+
+ @Override
+ protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FileTailInboundChannelAdapterFactoryBean.class);
+
+ if (element.hasAttribute("delay") || element.hasAttribute("end") || element.hasAttribute("reopen")) {
+ if (element.hasAttribute("native-options")) {
+ parserContext.getReaderContext().error(
+ "You cannot have 'native-options' if one or more of " +
+ "'delay', 'end' or 'reopen' is provided", element);
+ }
+ if (element.hasAttribute("task-scheduler")) {
+ parserContext.getReaderContext().error(
+ "You cannot have 'task-scheduler' one or more of " +
@artembilan Spring member

...if one or more...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@artembilan artembilan commented on an outdated diff
.../file/config/FileTailInboundChannelAdapterParser.java
((25 lines not shown))
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Gary Russell
+ * @since 3.0
+ *
+ */
+public class FileTailInboundChannelAdapterParser extends AbstractChannelAdapterParser {
+
+ @Override
+ protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FileTailInboundChannelAdapterFactoryBean.class);
+
+ if (element.hasAttribute("delay") || element.hasAttribute("end") || element.hasAttribute("reopen")) {
+ if (element.hasAttribute("native-options")) {
+ parserContext.getReaderContext().error(
@artembilan Spring member

How about just WARN it?
options isn't supported by ApacheCommonsFileTailingMessageProducer, so it just enough to ignore it in the FileTailInboundChannelAdapterFactoryBean in case of ApacheCommonsFileTailingMessageProducer.
Or from other side: if native-options has value we use OSDelegatingFileTailingMessageProducer, otherwise ApacheCommonsFileTailingMessageProducer.
I see it does not fit in your logic, however I want to find an algorithm, when my app will use Apache on Windows, otherwise - OS, without recompile.
At least via property-placeholder...

@garyrussell Spring member

Good point - I will change it to use "hasText"; that way a PPC can set them to "" when switching platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell garyrussell INT-2855 Polishing (Windows @Rule)
Handle case where a tail wrapper is installed but doesn't support
the options used in the test.
3547759
@garyrussell
Spring member

Hi Artem, can you try this @Rule? Thanks.

@artembilan
Spring member

Hi, Gary!
Well done! It's working now!
Thanks

@artembilan artembilan commented on an outdated diff
.../file/config/FileTailInboundChannelAdapterParser.java
((27 lines not shown))
+/**
+ * @author Gary Russell
+ * @since 3.0
+ *
+ */
+public class FileTailInboundChannelAdapterParser extends AbstractChannelAdapterParser {
+
+ @Override
+ protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FileTailInboundChannelAdapterFactoryBean.class);
+
+ if (StringUtils.hasText(element.getAttribute("delay")) ||
+ StringUtils.hasText(element.getAttribute("end")) ||
+ StringUtils.hasText(element.getAttribute("reopen"))) {
+ if (StringUtils.hasText(element.getAttribute("native-options"))) {
+ parserContext.getReaderContext().error(
@artembilan Spring member

But why it is still error?
I see you change it in the FileTailInboundChannelAdapterFactoryBean and now I can have smart OS-dependency strategy, but not via XML...

@garyrussell Spring member

Oops ... of course; I was forgetting the PPC; will change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@garyrussell garyrussell INT-2855 Remove Hard Errors in Parser
Allow setting any options in XML so a PropertyPlaceHolderConfigurer
can be used to adjust the settings between native and Apache
implementations, based on platform.
9f21c93
@garyrussell
Spring member

Pushed

@ghillert
Spring member

The PR works for me know.

@ghillert ghillert closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 17, 2013
  1. @garyrussell

    INT-2855 File Tailing Inbound Channel Adapter

    garyrussell committed
    Two implementations:
    
      - native 'tail' command (e.g. tail -F -n 0 /foo/bar)
      - Apache commons-io Tailer
  2. @garyrussell

    INT-2855 Polishing

    garyrussell committed
     - PR Reviews
     - Add what's new
  3. @garyrussell

    INT-2855 Polishing

    garyrussell committed
     - PR Comments
     - Removed CountDownLatch used only by test cases - wait for a field to be initialized instead
     - Fixed Race condition in OSDFTMP - run() referenced reader before it was available
  4. @garyrussell

    INT-2855 Polishing

    garyrussell committed
    Eliminate unnecessary CountDownLatch.
  5. @garyrussell

    INT-2855 Fix for Max OSX; Other Improvements

    garyrussell committed
     - Schedule Instead of Immediate Re-Run
         Mac OSX 'tail' terminates immediately when the file is
         missing.
     - Add delay when rescheduling a failed process
     - Add support for 'end' and 'reopen' options to Apache Tailer implementation
     - Clean up process destruction logic after failures
     - Add more debugging to threads
     - Add a JUnit @Rule so the OSDFTMP test doesn't fail on Windows
     - Add file path normalization so the tests pass on Windows
Commits on May 20, 2013
  1. @garyrussell

    INT-2855 Polishing (Windows @Rule)

    garyrussell committed
    Handle case where a tail wrapper is installed but doesn't support
    the options used in the test.
  2. @garyrussell

    INT-2855 Remove Hard Errors in Parser

    garyrussell committed
    Allow setting any options in XML so a PropertyPlaceHolderConfigurer
    can be used to adjust the settings between native and Apache
    implementations, based on platform.
Something went wrong with that request. Please try again.