SheppardDigital
SheppardDigital

Reputation: 3255

Spring Boot while loop in Async method halts application

I'm trying to create a watcher that looks for changes to a particular folder. I've created a watcher and put this within an Async method, but when I call it from a service the application pauses due to the while loop in the watcher method. It is like the method isn't being execute within a new thread.

Here is the class that contains the method I'm trying to execute;

    @Service
public class FileWatcher {

    @Async
    public Future<Object> watch(Path path, DataParser parser) throws IOException, InterruptedException {
        WatchService watchService = FileSystems.getDefault().newWatchService();

        path.register(
                watchService,
                StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_MODIFY);

        WatchKey key;
        while ((key = watchService.take()) != null) {
            for (WatchEvent<?> event : key.pollEvents()) {
                File file = new File(path.toString() + "/" + event.context());

                if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
                    parser.fileChanged(file);
                }

                if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
                    parser.fileCreated(file);
                }

                if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
                    parser.fileRemoved(file);
                }
            }
            key.reset();
        }

        return null;
    }

}

Then, I'm calling this within the constructor of a service.

@Service
public class SPIService {

    private final String DATAFOLDER = "/spi";

    private Path dataPath;

    public SPIService(@Value("${com.zf.trw.visualisation.data.path}") String dataPath) {
        this.dataPath = Paths.get(dataPath + DATAFOLDER);

        FileWatcher fileWatcher = new FileWatcher();
        try {
            fileWatcher.watch(this.dataPath, new SPIParser());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Why isn't this working? Is it because I'm calling the method from the constructor of a service?

Upvotes: 1

Views: 2933

Answers (1)

Kayaman
Kayaman

Reputation: 73558

You're using new FileWatcher() which means the instance isn't a managed bean. This also means that @Async is ignored (which explains your application halting). You need to @Autowire FileWatcher instead.

Note also that your solution seems very suspicious to me, not only for having an infinite loop, but having one in an @Async method (this has some important consequences). I would at least use a single threaded threadpool for it.

Upvotes: 3

Related Questions