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();
        }
    }
}


Reply via email to