Dane Balia
Dane Balia

Reputation: 5367

Observer pattern Right for File Monitoring?

I am interested to know if the Observer Pattern is correct approach for implementing code to monitor log files and their changes?

I am currently using it, but there seems to be an anomaly that I can't quite explain. Basically, i create a Class called FileMonitor that has a timer that fires, that iterates a list of unique files looking for a changed "lastmodified date".

Upon finding it, a list of Listeners are iterated through to find the matching file, and it's fileChanged event is notified. It then begins to process the lines that were added in the file.

So to make my question more succinct:

  1. Does the Observer Pattern fit what I am trying to do? (Currently I have one Listener per file)
  2. Is there any possibility of 'concurrency issues' given that there is more than one File to monitor?

Thanks

Upvotes: 3

Views: 6407

Answers (4)

user2030471
user2030471

Reputation:

If you do not want to use Java 7, you can get the same behavior with Apache IO.

From the official documentation:

FileAlterationObserver represents the state of files below a root directory, checking the filesystem and notifying listeners of create, change or delete events.

Here is how you can add listeners to define operations to be executed when such events happen.

  File directory = new File(new File("."), "src");
  FileAlterationObserver observer = new FileAlterationObserver(directory);
  observer.addListener(...);
  observer.addListener(...);

You will have to register the oberver(s) with a FileAlterationMonitor. Continuing from the same documentation:

  long interval = ...
  FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
  monitor.addObserver(observer);
  monitor.start();
  ...
  monitor.stop();

Where interval is the amount of time (in miliseconds) to wait between checks of the file system.

Look for package named org.apache.commons.io.monitor in the library.

Upvotes: 4

Ajay George
Ajay George

Reputation: 11875

Does the Observer Pattern fit what I am trying to do? (Currently I have one Listener per file)

Yes it does.

Is there any possibility of 'concurrency issues' given that there is more than one File to monitor?

If you have multiple threads removing and adding listeners to a list backed up by an ArrayList you run the risk of ConcurrentModificationException . Use a CopyOnWriteArrayList instead.

IIRC Effective java has an article containing a good example on the same.

Upvotes: 3

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

Java 7 has introduced WatchService which watches registered objects for changes and event.

A Watchable object is registered with a watch service by invoking its register method, returning a WatchKey to represent the registration. When an event for an object is detected the key is signalled, and if not currently signalled, it is queued to the watch service so that it can be retrieved by consumers that invoke the poll or take methods to retrieve keys and process events. Once the events have been processed the consumer invokes the key's reset method to reset the key which allows the key to be signalled and re-queued with further events.

File systems may report events faster than they can be retrieved or processed and an implementation may impose an unspecified limit on the number of events that it may accumulate. Where an implementation knowingly discards events then it arranges for the key's pollEvents method to return an element with an event type of OVERFLOW. This event can be used by the consumer as a trigger to re-examine the state of the object.

Example -

Path myDir = Paths.get("D:/test");       

    try {
       WatchService watcher = myDir.getFileSystem().newWatchService();
       myDir.register(watcher, StandardWatchEventKind.ENTRY_CREATE, 
       StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY);

       WatchKey watckKey = watcher.take();

       List<WatchEvent<?>> events = watckKey.pollEvents();
       for (WatchEvent event : events) {
            if (event.kind() == StandardWatchEventKind.ENTRY_CREATE) {
                System.out.println("Created: " + event.context().toString());
            }
            if (event.kind() == StandardWatchEventKind.ENTRY_DELETE) {
                System.out.println("Delete: " + event.context().toString());
            }
            if (event.kind() == StandardWatchEventKind.ENTRY_MODIFY) {
                System.out.println("Modify: " + event.context().toString());
            }
        }

    } catch (Exception e) {
        System.out.println("Error: " + e.toString());
    }
}

Reference - link

Upvotes: 5

TheWhiteRabbit
TheWhiteRabbit

Reputation: 15758

I'd suggest to go for NIO

and File Watcher services - Watching File For Changes

Upvotes: 0

Related Questions