The Watch Service was introduced in Java 7 as a “thread-safe” service responsible for watching objects for changes.

The most popular use of this API would be to use it as way to monitor a folder of files for changes such as: addition of new files, deletion of files, file renames, etc.


Implementing a WatchService

The WatchService is dependent on the FileSystem, the first step of creating a new Service is to obtain the underlying file system:

Every object needs to be explicitly registered with the newly created service. In our particular case we will register a Path instance (a folder).

After we register the object, we also need to specific events the service need to watch.

Eg.:

  • StandardWatchEventKinds.ENTRY_CREATE: This event triggers when a folder entry is created, or a new entry is moved or renamed.
  • StandardWatchEventKinds..ENTRY_DELETE: This event is triggered when a folder/file is deleted, moved or renamed.
  • StandardWatchEventKinds.ENTRY_MODIFY: This event is pretty-platform dependent. Usually is triggered when the contents of a file is modified. But on some file systems it can also trigger when the attributes of that particular file are modified.
  • StandardWatchEventKinds.OVERFLOW: Indicates that an event has been lost.

The following code will register ENTRY_CREATE, ENTRY_DELETE and ENTRY_MODIFY to the home folder:

For every Path instance we are registering we will receive an WatchKey instance.

To wait for incoming events we will need to write an infinite loop:

In this loop we will be able to poll for obtaining WatchKey instances.

We can also add a timing interval for polling (if we don’t need an instant feedback on the events):

A WatchKey can have the following states:

  • Ready: The WatchKey is ready to accept events.
  • Signaled: In this state the WatchKey has at least one event that occurred and it was queued.
  • Invalid: In this state the key is considered to be no longer valid.

So the next step will be to retrieve the pending events from the WatchKey. There can be multiple events that were triggered. Those events are queued. The code to retrieve the pending events is:

To obtain the Path from the watchEvent we will need to do something like this:

The last step of the implementation is to put key back into it’s Ready step.

Also you should also take in consideration that if the loops break (eg.: because of an error) you need to explicitly close the Watch Service:

Or, since Java 7, include the opening of the WatchService in the new try() block:


Putting all the code togheter

Please take in consideration that in our particular case we are only going to watch the Home folder, and not the whole sub-tree of folders. If you wish to watch the whole sub-tree for modifications you will need to register a watch service for every folder in the tree.

To obtain the list of sub-folders of a given folder, I recommend you to read my previous article called: Java 7 NIO.2 – Recursive folder walks

Also you will need to maintain the collection of watchers in the case you are creating/deleting new/existing sub-folders.

The Watch Service API is a low-level approach, so maybe it’s best for you if you write your own high-level mechanism, or use an already-existing solution.

I will create new files/folders inside my home directory the output will look like: