Search code examples
javaspringwatchservice

WatchService with spring


I am trying to execute "WatchService" with spring but it is looking impossible because when I am trying to run this service at the time of application context but loading of spring context becoming stop when control come at

key = watcher.take();

due to this loading of application context is not happening.

below is the full code

@Component
public class DirectoryWatchDemo {


    @PostConstruct
    public static void test(){
        try {
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Path dir = Paths.get("C:/test");
            dir.register(watcher, ENTRY_CREATE);

            System.out.println("Watch Service registered for dir: " + dir.getFileName());

            while (true) {
                WatchKey key;
                try {
                    key = watcher.take();
                } catch (InterruptedException ex) {
                    return;
                }

                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
                    Path fileName = ev.context();

                    System.out.println(kind.name() + ": " + fileName);

                    if (kind == ENTRY_MODIFY &&
                            fileName.toString().equals("DirectoryWatchDemo.java")) {
                        System.out.println("My source file has changed!!!");
                    }
                }

                boolean valid = key.reset();
                if (!valid) {
                    break;
                }
            }

        } catch (IOException ex) {
            System.err.println(ex);
        }
    }

}

I am doing in this way because I do not want to execute "WatchService" manually.


Solution

  • It is because you have an endless loop, and therefore the method invocation of @PostConstruct never return.

    (it seams strange to me, that @PostConstruct works with static methods, but maybe this works)

    So the solution is that you start an new thread for your watcher. You could do this in different ways:

    • just start an new thread
    • Add @Async to that method (I do not know if this works for @PostConstruct methods) (the major drawback is, that this starts BEFOR the complete application context is initialize)
    • abuse the @Scheduler annotation: @Scheduled(fixedDelay = Long.MAX_VALUE) - (the advantage over @PostConstruct+@Async is: that it works for sure and it starts just AFTER the complete context is initialized)