Java Quiz Player

Java 7 NIO 2 API's Watch Service - Notes and Example

Aug 10, 2013

This blog post is about using Java SE 7's Watch Service API. This includes an example, its description and notes on usage in applications.

This post's contents:

1. Introduction

java.nio.file package has a file change notification API, called the Watch Service.

A watch service watches registered objects for changes and the resulting events. For example, a file manager application may use a watch service to monitor a directory for changes, so that it can update its display of the list of files when files are created, renamed or deleted.

The watch service usage overview steps:

2. The Example

The following is an example application using the watch service. This describes the API's usage steps. The complete code WatchServiceExample1.java is listed at the end of this post.

2.1. Create a new watch service for the file system.

WatchService watchService = FileSystems.getDefault().newWatchService();

2.2. Get the directory path to be watched (monitored).

String watchedDir = "D:\\JavaWatchService\\testdir1";
Path dir = Paths.get(watchedDir);

2.3. Register the directory to be monitored with the watch service.

Register the object to be monitored with the watch service. This is the directory's path object. The registered object is required to implement the Watchable interface. Path is an interface, and extends the Watchable.

WatchKey watchKey = dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);

2.3.1. Watch Event Kinds:

The events parameter is the events (event identifiers) to register - ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY and OVERFLOW are the standard event kinds. These are defined in the StandardWatchEventKind class, as fields of type WatchEvent.Kind<T>. One or all of these events can be specified.

The standard events (except OVERFLOW) are defined as WatchEvent.Kind<Path>. The context for these events is the relative path between this directory's path and the file path that is created, deleted, or modified.

The OVERFLOW is defined as WatchEvent.Kind<Object>. The OVERFLOW event need not be registered to receive it. This is a special event to indicate that events may have been lost or discarded.

2.3.2. Watch Key:

The register() method returns a WatchKey object. The watch key is a token representing the registration of a Watchable object (the directory's Path) with a watch service. WatchKey is defined as an interface in the API.

This watch key is valid, and remains valid until cancelled or closed.

A watch key has 3 states - (1) a ready state when created and after it is reset, (2) a state at event detection and being signaled, and (3) a not valid state. All events are retrieved (and removed) from the watch key. The retrieved events are processed as required by an application.

At the end of processing all the events, the watch key is to be reset and ready (state) for the next set of the monitored watch service events.

A watch key is cancelled by using the cancel() method, by closing the watch service, or when not accessible.

Useful WatchKey methods are: cancel(), reset() and pollEvents().

2.4. Get and process the events that occur.

The events occur when the registered directory has changes. The events are queued. The consumer process using the watch service invokes the take() or poll() methods. These methods return the watch key with these events.

2.4.1. Wait for the watch key to be signaled of events.

watchKey = watchService.take();
There are three WatchService methods to get the watch key with the queued events:

2.4.2. Get and process the events for the watch key.

(i) Get the list of events from the watch key. The WatchKey's pollEvents() method returns the events (watch events) as a List collection of type WatchEvent<?>.

List<WatchEvent<?>> eventList = watchKey.pollEvents();

(ii) Iterate over the list of events and process each event.

for (WatchEvent<?> genericEvent : eventList) {

Process the event kinds, one at a time, as required. The WatchEvent's kind() method returns the event kind (WatchEvent.Kind).

If (genericEvent.kind()== OVERFLOW) {
    // do something, like process the next event in the event list
}

In case of the standard events other than the OVERFLOW, the file Path (and the file name) associated with the event can be retrieved, using the WatchEvent's context() method.

if (genericEvent.kind() == ENTRY_CREATE) {
    // do something as required
    Path filePath = (Path) genericEvent.context();
}

NOTE: A cast is required to the Path. The context (the context object associated with the event) of the genericEvent (WatchEvent<?>) is of generic type parameter ?. And the WatchEvent.Kind<type parameter> for the standard (non OVERFLOW) event is of type Path.

(iii) Process the next iterator element - the next event (ii).

2.4.3. Reset the watch key.

At this point, all events for the watch key are processed. Reset the watch key.

boolean validKey = watchKey.reset();

Wait for the watch key to be signaled for the next set of events - (4a).

2.5. Close the watch service.

watchService.close();

NOTE:

3. The Example's Output

The example application is run from Windows OS command prompt.

Step1: Start the example application.

osprompt> java WatchServiceExample1
The console output:
Watch service example 1:
Registered dir: D:\JavaWatchService\testdir1
    Watch key (valid): true
Waiting for watch key to be signaled...
Notes from the console output:

Step 2: Note the file change notification action output.

From a Windows File Manager application, navigate to the directory being monitored; in the example, it is the D:\JavaWatchService\testdir1. Perform file actions like, add, modify, rename, copy and delete on any file(s).

Here are some actions and the related results in the console output.

Action 1: Create a file.

Right-click > New > Notepad Document: This action creates a Notepad document file 'New Text Document.txt' in the watched directory 'testdir1'.

The console output:
Process the pending events for the watch key: 1
Path event kind: ENTRY_CREATE
    File: New Text Document.txt
Watch key reset.
Waiting for watch key to be signaled...
Note from the console output:

Action 2: Create a file (differently than that of the Action 1).

Open a document application (like MS Word or Notepad) > Open a new document file > Save the file in the watched directory 'testdir1'.

The console output:
Process the pending events for the watch key: 2
Path event kind: ENTRY_CREATE
    File: test1.txt
Path event kind: ENTRY_DELETE
    File: test1.txt
Watch key reset.
Waiting for watch key to be signaled...
Process the pending events for the watch key: 1
Path event kind: ENTRY_CREATE
    File: test1.txt
Watch key reset.
Waiting for watch key to be signaled...
Process the pending events for the watch key: 1
Path event kind: ENTRY_MODIFY
    File: test1.txt
Watch key reset.
Waiting for watch key to be signaled...

Note from the console output - there are three watch keys and multiple events for each one.

Action 3: Rename a file.

Rename a file in the watched directory; for example 'test1.txt' is renamed to 'test1renamed.txt'.

The console output:
Process the pending events for the key: 3
Path event kind: ENTRY_DELETE
    File: test1.txt
Path event kind: ENTRY_CREATE
    File: test1renamed.txt
Path event kind: ENTRY_MODIFY
    File: test1renamed.txt
Watch key reset.
Waiting for watch key to be signaled...

Note from the console output - there are three events; one for the file before renaming it, and two for the renamed file.

Other File Actions:

Copy a file, delete a file and modify (open an existing document file in an editor, change some text and save) a file.

4. File Actions and Events

This shows various file change actions and the respective resulting event(s). Note that these are from the output of the example.

4.1. File Actions from Windows

File Actions Events
Create a file from Windows file manager application's menu: File > New > (Notepad) Document Create
Create new file from a Notepad application; and save the file. Create Modify Delete
Rename a file. Create Modify Delete
Update an existing file - edit and save an existing text file using Notepad application. Modify
Delete a file. Delete
Copy a file; either drag and drop, or copy and paste. In this case the destination file does not exist. Create Modify
Copy and replace a file. In this case the source and destination file names are same. Modify

4.2. File Actions from a Java Program

NOTE: The results are based on a Java program that uses Java 7 file NIO 2 API.

File Actions Events
Create a new file. Create
Update an existing file. Modify
Rename a file. Create Modify Delete
Delete a file. Delete
Copy a file (source and target files are different). Create Modify
Copy and replace a file. Create Modify Delete

5. Notes on usage of Watch Service in Applications

Some applications using Watch Service:

6. WatchServiceExample1.java

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.FileSystems;
import java.nio.file.WatchService;
import java.nio.file.WatchKey;
import java.nio.file.WatchEvent;
import static java.nio.file.StandardWatchEventKinds.*;
import java.io.IOException;
import java.util.List;
public class WatchServiceExample1 {
    private static final String watchedDir = "D:\\JavaWatchService\\testdir1";
    public static void main(String [] args)
            throws IOException {
        new WatchServiceExample1().doProcess();
    }
    private void doProcess()
            throws IOException {
        // (1) Create a new watch service
        WatchService watchService = FileSystems.getDefault().newWatchService();
        System.out.println("Watch service example 1:");
        // (2) Get the directory to be monitored	
        Path dir = Paths.get(watchedDir);
        // (3) Register the directory to be monitored with the watch service
        WatchKey watchKey = dir.register(watchService,
                ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);			
        System.out.println("Registered dir: " + dir.toString());
        System.out.println("    Watch key (valid): " + watchKey.isValid());
        // (4) Get and process the events that occur
        INFINITE_WHILE_LOOP:
        while(true) {
            // (4a) Wait for the watch key to be signaled of events
            try {
                System.out.println("Waiting for watch key to be signaled...");
                watchService.take();
            }
            catch (InterruptedException ex) {
                ex.printStackTrace();
                break INFINITE_WHILE_LOOP;
            }
            // (4b) Get and process the events for the watch key
            List<WatchEvent<?>> eventList = watchKey.pollEvents();
            System.out.println("Process the pending events for the watch key: " +
                    eventList.size());
            EVENT_FOR_LOOP:
            for(WatchEvent<?> genericEvent: eventList) {
                // Retrieve and process the event kind
                if (genericEvent.kind() == OVERFLOW) {
                    System.out.println("Overflow event");
                    continue EVENT_FOR_LOOP; // next event
                }
                // else, genericEvent.kind() is WatchEvent.Kind<Path>
                // values: ENTRY_CREATE... 
                System.out.println("Path event kind: " + genericEvent.kind());
                // Retrieve the file name associated with the event
                Path filePath = (Path) genericEvent.context();
                System.out.println("    File: " + filePath.toString());
            } // end EVENT_FOR_LOOP (for a watch key)
            // (4c) Reset the watch key
            boolean validKey = watchKey.reset();
            System.out.println("Watch key reset.");
            if (! validKey) {
                System.out.println("Invalid watch key, close the watch service");
                break INFINITE_WHILE_LOOP;
            }
        } // end, INFINITE_WHILE_LOOP
        // (5) Close the watch service
        watchService.close();
        System.out.println("Watch service closed.");
    } // doProcess()
} // WatchServiceExample1

7. Download

Download source code here: WatchServiceExample.zip

8. References

Link to Java SE 7 API's java.nio.file (NIO 2): http://docs.oracle.com/javase/7/docs/api/java/nio/file/package-summary.html

Return to top