Hi Maybe you can leverage Felix FileInstall implementing a ArtifactDeployer. It’s what Karaf uses for deployers. It would simplify your code by focusing on artifact handling logic.
Regards JB Le mar. 28 janv. 2025 à 21:52, Matthias Wegner <matthias.weg...@email.de> a écrit : > 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(); > } > } > } > > >