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:
So und hier mein Test :
Hat jemand einen Tipp für mich
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