javaxmlniowatchservice

Java NIO WatchService


I have Java project that we need to keep listening some path to detect if there is any new XML file and if true, we need to process it through few other rules.

The WatchService is doing very well to discover if I have a new file there to be processed, but I wasnt able to manage it so I could read the file, I just gives me back the file name, from the event.

Is there any way to that with WatchService? If not, whats another sugestion to reach?

Thanks.


Solution

  • Sure, you can easely to that:

    1. Create the watch service:

       WatchService watchService = null;
      
       try {
           watchService = FileSystems.getDefault().newWatchService();
           Path path = get(pathToSee);
           path.register(watchService, new WatchEvent.Kind[]{ENTRY_MODIFY, ENTRY_CREATE}, SensitivityWatchEventModifier.HIGH);
           watchEvent(watchService, path);
           log.info("Watch Service has ben created!");
       } catch (IOException e) {
           log.error("Exception has ben throw when the service have tried to createWatchService()", e);
       }
      

    Note: If you have a large amount of files to be added, you can put:

    SensitivityWatchEventModifier.HIGH
    

    To increase sensitivity.

    1. Watch if have changes in you directory:

       WatchKey key;
       while (true) {
           try {
               if ((key = watchService.take()) == null) break;
      
               for (WatchEvent<?> event : key.pollEvents()) {
                   log.info("Event kind:" + event.kind()
                           + ". File affected: " + event.context() + ".");
      
                   String fileName = event.context().toString();
                   File directory = path.toFile();
                   yourService.readContent(directory, fileName);
               }
               key.reset();
           } catch (InterruptedException | IOException e) {
               log.error("InterruptedException when try watchEvent()" + e);
           }
       }
      
    2. And finally, you can do what you want to do with that infos:

       try (BufferedReader br = new BufferedReader(new FileReader(directory + "/" + fileName))) {
           String strLine;
           while ((strLine = br.readLine()) != null) {
                   }
               }
           }
       }
      

    Tips:

    1. You can create a separete thread to do that, or use Spring @Async to create a separete thread to process this information and increase concurrency in your application.

    2. You can use Apache Commons you to do that too!

    e.g:

    public void getAll() throws Exception {
        FileAlterationObserver observer = new FileAlterationObserver(pathToSee);
        observer.addListener(new FileAlterationListenerAdaptor() {
    
            @SneakyThrows
            @Override
            public void onFileCreate(File file) {
                
                
            }
    
            @Override
            public void onFileDelete(File file) {
                
            }
        });
    }