Hi All, I try since hours to build a Thread-Safe OSGi Service which watches a directory for file changes and executes on modification. See description bellow. Can someone give me a tip a working example for a thread safe service?
Regards, Matthias PROBLEM The problem is, that I get not the Thread correctly registered. I have already successfully registered some services in activator and bundle Context. But somehow I did not get this started on the DirectoryWatcher. And in different experiments and when the execution starts, then I get the following erros: ERROR ON EXCECUTION Exception in thread java.lang.NoClassDefFoundError: org/rogatio/k3/base/service/WorkitemService at org.rogatio.k3.base.service.DirectoryWatcher.run(RecursiveDirectoryWatcher.java:91) at java.base/java.lang.Thread.run(Thread.java:829) ... Caused by: java.lang.ClassNotFoundException: Unable to load class 'com.fasterxml.jackson.databind.ObjectMapper' because the bundle wiring for org.rogatio.k3-base-core is no longer valid. ERROR ON INSTALLING BUNDLE Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=k3-base; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=k3-base)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve k3-base/1.0.0.SNAPSHOT: missing requirement [k3-base/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=org.rogatio.k3-base-core; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve org.rogatio.k3-base-core/1.0.0.SNAPSHOT: missing requirement [org.rogatio.k3-base-core/1.0.0.SNAPSHOT] osgi.service; filter:="(objectClass=org.rogatio.k3.base.service.RecursiveDirectoryWatcher)"; effective:=active]] CODE ---------------------------------------------------------------------------- import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; public class RecursiveDirectoryWatcher implements Runnable { private final Path rootDir; private final WatchService watchService; private final Map<WatchKey, Path> keyToPathMap; public RecursiveDirectoryWatcher(String rootDir) throws IOException { this.rootDir = Paths.get(rootDir); this.watchService = FileSystems.getDefault().newWatchService(); this.keyToPathMap = new HashMap<>(); registerAll(this.rootDir); // Register all subdirectories } // Register a directory and all its subdirectories private void registerAll(final Path start) throws IOException { Files.walkFileTree(start, new SimpleFileVisitor<>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { registerDirectory(dir); return FileVisitResult.CONTINUE; } }); } // Register a single directory with the WatchService private void registerDirectory(Path dir) throws IOException { WatchKey key = dir.register( watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE ); keyToPathMap.put(key, dir); System.out.println("Watching directory: " + dir); } @Override public void run() { System.out.println("Starting to watch directory: " + rootDir); while (true) { WatchKey key; try { key = watchService.take(); // Wait for events } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Directory watching interrupted."); break; } Path dir = keyToPathMap.get(key); if (dir == null) { System.err.println("WatchKey not recognized!"); continue; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); // Resolve the relative file name to an absolute path Path name = (Path) event.context(); Path fullPath = dir.resolve(name); System.out.println("Event: " + kind + " on file: " + fullPath); // EXECUTE HERE THE CODE OF AN OSGI-BUNDLE which parses JSON-Files // If a new directory is created, register it if (kind == StandardWatchEventKinds.ENTRY_CREATE) { try { if (Files.isDirectory(fullPath)) { registerAll(fullPath); } } catch (IOException e) { System.err.println("Failed to register directory: " + fullPath); } } } // Reset the key to continue watching boolean valid = key.reset(); if (!valid) { keyToPathMap.remove(key); if (keyToPathMap.isEmpty()) { System.out.println("All directories are no longer valid. Stopping."); break; } } } } public static void main(String[] args) { String directoryToWatch = "/path/to/root/directory"; try { // Create a new thread for the directory watcher Thread watcherThread = new Thread(new RecursiveDirectoryWatcher(directoryToWatch)); watcherThread.start(); // Main thread can do other tasks while the watcher thread runs System.out.println("Main thread is free to do other tasks..."); } catch (IOException e) { e.printStackTrace(); } } }