Search code examples
javafilesystemwatcherapache-commons-jci

Apache JCI FilesystemAlterationMonitor processes changes for existing folder contents on startup


I am using Apache JCI's FAM (FileAlterationMonitor) in a Java OSGi Service to monitor and handle changes in the FileSystem. Everything seems to be working fairly well except whenever I start the Service (which starts the FAM using the code below), FAM picks up on ALL the changes that exist in the directory.

Currently I am watching /tmp /tmp includes a subtree: /tmp/foo/bar/cat/dog

Everytime I start the service and which starts FAM, it reports DirectoryCreate events for:

/tmp/foo
/tmp/foo/bar
/tmp/foo/bar/cat
/tmp/foo/bar/cat/dog

Even if no changes have been made to any part of that subtree.

Code run on service activation:

File watchFolder = new File("/tmp"); 
watchFolder.mkdirs();

fam = new FilesystemAlterationMonitor();
fam.setInterval(1000);
fam.addListener(watchFolder, listener);
fam.start();
// I've already tried adding:
listener.waitForFirstCheck();

Listener example:

private FileChangeListener listener = new FileChangeListener() {
    public void onDirectoryChange(File pDir) { System.out.println(pDir.getAbsolutePath()); }
    public void onDirectoryCreate(File pDir) { System.out.println(pDir.getAbsolutePath()); }
    ...
}

Solution

  • Yes, that's one very annoying feature of JCI. When monitoring is started, it will notify you of all the files and directories it finds with calls to onXxxCreate(). I think you have the following options

    • After starting the monitoring, wait for some time (couple of seconds) in your FileChangeListener callback implementation before you actually process the events coming from JCI. That's what I did in a project and it works fairly well, although there is the possibility that you miss an actual file creation that just happens within the "grace period"
    • Take the sources of JCI and modify them to use two new event methods onDirectoryFound(File)and onFileFound(File) that will only be fired when files and directories are found on startup of the monitoring
    • Take a look at java.nio.file.WatchService that comes with Java 7. IMO the best option, as it uses native methods internally in order to be notified of changes by the OS, instead of starting a thread and checking periodically. With JCI, you may get delays in the range of several seconds until changes are propagated to your callbacks