FolderWatcher mit WatchService funktioniert nur bedingt

Diskutiere FolderWatcher mit WatchService funktioniert nur bedingt im Allgemeine Java-Themen Bereich.
T

tummigummi1984

Hallo ich möchte gerne einen Folder Watcher implementieren, um auf Änerungen in einem Verzeichnis zu reagieren. Ich nutze dazu den WatchService. Allerdings funktioniert mein Code in meinem Test nur "zufällig" also mal geht es und mal eben nicht.

Hier mein Code als mein Folder Watcher:
Java:
@Slf4j
public class FolderWatcher implements Runnable {

    @NonNull
    private Path monitorDir;

    @Getter
    private boolean running = true;

    @NonNull
    private List<PropertyChangeListener> listenerList = Lists.newLinkedList();

    /**
     * default constructor
     *
     * @param monitorDir - the dir to monitor
     */
    public FolderWatcher(Path monitorDir) {
        log.info("create a new folder watcher object monitor the dir '{}'", monitorDir.toFile().getAbsolutePath());

        this.monitorDir = monitorDir;
    }

    public void addObserver(PropertyChangeListener listener) {
        log.info("add listener");
        listenerList.add(listener);
    }

    @SneakyThrows
    @Override
    public void run() {

        WatchService watchService = FileSystems.getDefault().newWatchService();
        monitorDir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);

        while (running) {
            log.debug("start monitoring '{}'", monitorDir.toFile().getAbsolutePath());

            WatchKey key;
            while ((key = watchService.take()) != null) {
                for (WatchEvent<?> event : key.pollEvents()) {
                    Path filePath = (Path) key.watchable();
                    filePath = filePath.resolve(event.context().toString());

                    if (filePath.toFile().getAbsolutePath().endsWith("csv")) {
                        log.debug("is csv file '{}'", filePath.toFile().getAbsolutePath());

                        for (PropertyChangeListener listener : listenerList){
                            listener.propertyChange(new PropertyChangeEvent(this, "file", filePath, filePath));
                        }
                    }
                }
                key.reset();
            }
        }
    }

}
So und hier mein Test :

Java:
@Slf4j
class FolderWatcherTest {

    private static Path INCOMING_DIR = Paths.get("src", "test", "resources", "incoming");
    private static Path SOURCE_CSV_FILE = Paths.get("src", "test", "resources", "testCSVFiles", "TestFile.csv");
    private static Path TARGET_CSV_FILE = Paths.get("src", "test", "resources", "incoming", "TestFile.csv");

    @SneakyThrows
    @BeforeAll
    private static void setup() {
        log.debug("create '{}'", INCOMING_DIR);
        Files.createDirectories(INCOMING_DIR);
        assertTrue(Files.exists(INCOMING_DIR));
    }

    @SneakyThrows
    @AfterAll
    private static void cleanup() {
        log.debug("delete '{}'", TARGET_CSV_FILE);
        Files.delete(TARGET_CSV_FILE);
        assertFalse(Files.exists(TARGET_CSV_FILE));

        log.debug("delete '{}'", INCOMING_DIR);
        Files.delete(INCOMING_DIR);
        assertFalse(Files.exists(INCOMING_DIR));
    }

    private void writeSourceFileContentToTargetFile(File sourceFile, File targetFile) throws Exception {
        Reader reader = new InputStreamReader(new FileInputStream(SOURCE_CSV_FILE.toFile()), StandardCharsets.ISO_8859_1);
        BufferedReader bufferedReader = new BufferedReader(reader);

        Writer writer = new OutputStreamWriter(new FileOutputStream(TARGET_CSV_FILE.toFile()));
        BufferedWriter bufferedWriter = new BufferedWriter(writer);
        bufferedReader.lines().forEach(line -> {
            try {
                bufferedWriter.write(line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        bufferedWriter.flush();
        bufferedWriter.close();
        bufferedReader.close();
    }

    @Test
    @DisplayName("first start folder watcher and then write the file")
    public void testFirstStartTheFolderWatcherAndThenWriteTheFile() throws Exception {
        Listener listener = new Listener();
        FolderWatcher folderWatcher = new FolderWatcher(INCOMING_DIR);
        folderWatcher.addObserver(listener);
        new Thread(folderWatcher).start();

        writeSourceFileContentToTargetFile(SOURCE_CSV_FILE.toFile(), TARGET_CSV_FILE.toFile());

        Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> folderWatcher.isRunning() == true);
        Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> listener.getNumberOfAffectedFiles() > 0);
    }
}

Hat jemand einen Tipp für mich
 
MoxxiManagarm

MoxxiManagarm

Das musst du schon genauer spezifizieren. Was heißt es geht nicht?
 
T

tummigummi1984

Danke für deinen hinweis. Also der Folderwatcher soll ja nach Dateien in dem Verzeichnis lauschen (monitorDir;) .
Anschließend sollen alle Listener informiert werden

Der Test legt dieses Verzeichnis an und kopiert eine Datei dorthin. Es soll nun geprüft werden ob der Listener diese Datei als notifcation bekommen hat.

Das lauschen auf die Datei funktioniert leider nicht zuverlässig. Mal finet der FolderWathcer diese Datei und mal eben nicht
 
MoxxiManagarm

MoxxiManagarm

Ok, also ist die Auusgangslage: Mal funktioniert der Test testFirstStartTheFolderWatcherAndThenWriteTheFile, mal nicht?!
 
mihe7

mihe7

Was passiert denn, wenn Du nach der Erzeugung des Threads ein klein wenig wartest?
 
Thema: 

FolderWatcher mit WatchService funktioniert nur bedingt

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben