Daniel Mitterdorfer

Perlock - Path Watching without Headaches


Image by Sandra; license: CC

As I have written in my previous post the JDK 7 WatchService API is too low level to be used directly in an application. To my surprise, to this day no Java library has existed that abstracts the JDK 7 WatchService API and provides an easy high level API on top.

A Simplified API: Perlock

Therefore I created perlock (short for Path-Sherlock). It supports the standard use case of watching files or directories for modifications and performing some action then. It consists of a very small API with two interfaces and two classes:

  • PathWatcher for watching paths. It provides lifecycle methods to start and stop watching.
  • PathWatcherFactory to create a PathWatcher for a specific path.
  • PathChangeListener as a callback interface to get notified of file system changes. This is the only interface that has to be implemented by clients. The library also provides an AbstractPathChangeListener convenience base class that implements all callback methods as no-ops.

Suppose, you want to print a message every time a file is created in the path /tmp. First, implement the callback:

public class SamplePathLogger extends AbstractPathChangeListener {
    public void onPathCreated(Path path) {
        System.out.println("Created: '" + path + "'");    

Next, create a PathWatcher and start watching:

Path pathToWatch = Paths.get("/tmp");
ExecutorService executorService = Executors.newFixedThreadPool(1);
PathWatcherFactory pathWatchers = new PathWatcherFactory(executorService);
PathWatcher watcher = pathWatchers.createNonRecursiveWatcher(pathToWatch, new SamplePathLogger());

That’s it. When you are done, call watcher.stop() and shutdown the thread pool. You might wonder why the PathWatcherFactory needs an ExecutorService. Path watching is always performed in a background thread (one per PathWatcher instance) otherwise path watching would block your entire program.

Using Perlock

If you want to try perlock, clone the Github repo, try the example application or build the binary yourself with Gradle.

Questions or comments?

Just ping me on Twitter