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