I have this Java code which I want to use to monitor file changes into directory:
private static String folderPath = "D:\\Import";
public static void main(final String[] args) throws IOException, InterruptedException {
System.out.println("Running file verifier");
System.out.println("monitoring folder " + folderPath);
EntityImportRequestsJob sql = new EntityImportRequestsJob();
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get(folderPath);
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("Event kind:" + event.kind() + ". File affected: " + event.context() + ".");
if (event.kind().equals(StandardWatchEventKinds.ENTRY_DELETE)) {
Instant start = Instant.now();
boolean flag = true;
while(flag) {
while ((key = watchService.take()) != null) {
HashMap<String, List> map = sql.checkFileImport();
List values = map.get(event.context()); // get values by file name
if(values.contains("Completed")){
// exit the monitoring while loop
flag = false;
}
}
Thread.sleep(1000);
}
Instant end = Instant.now();
System.out.println(Duration.between(start,end));
long seconds = TimeUnit.MILLISECONDS.toSeconds(Duration.between(start,end).getSeconds());
long minutes = TimeUnit.MILLISECONDS.toMinutes(Duration.between(start,end).getSeconds());
System.out.format("Execution time %d minutes %d seconds", minutes, seconds);
}
}
key.reset();
}
watchService.close();
}
How I can start this code when Spring Project is successfully started?
You can start this code when a Spring project is successfully started by creating a Bean for it and annotating it with @EventListener
and ApplicationReadyEvent
like this:
@Component
public class FileMonitor {
private static String folderPath = "D:\\Import";
@EventListener(ApplicationReadyEvent.class)
public void startMonitoring() throws IOException, InterruptedException {
System.out.println("Running file verifier");
System.out.println("monitoring folder " + folderPath);
EntitiesImportRequestsJob sql = new EntitiesImportRequestsJob();
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get(folderPath);
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("Event kind:" + event.kind() + ". File affected: " + event.context() + ".");
if (event.kind().equals(StandardWatchEventKinds.ENTRY_DELETE)) {
Instant start = Instant.now();
boolean flag = true;
while(flag) {
while ((key = watchService.take()) != null) {
HashMap<String, List> map = sql.checkFileImport();
List values = map.get(event.context()); // get values by file name
if(values.contains("Completed")){
// exit the monitoring while loop
flag = false;
}
}
Thread.sleep(1000);
}
Instant end = Instant.now();
System.out.println(Duration.between(start,end));
long seconds = TimeUnit.MILLISECONDS.toSeconds(Duration.between(start,end).getSeconds());
long minutes = TimeUnit.MILLISECONDS.toMinutes(Duration.between(start,end).getSeconds());
System.out.format("Execution time %d minutes %d seconds", minutes, seconds);
}
}
key.reset();
}
watchService.close();
}
}
Make sure the FileMonitor
class is in a package that is scanned by Spring.
And also make sure EntitiesImportRequestsJob
is properly instantiated and managed by spring container, otherwise you will get a NullPointerException
Your code looks like a constantly running background job.
To run it and not block the main thread with all those watchService.take()
and Thread.sleep(1000)
the best approach would be to use the Spring's TaskExecutor
abstraction.
You'll have to wrap your code into a Runnable
which then could be fed to a task executor.
To launch this task I'd use an ApplicationRunner
- Spring will run it after the application context is fully initialized.
Below is an example of what it might look like (uses lombok
library).
Runnable:
@Slf4j
class FileVerificationTask implements Runnable {
private static String folderPath = "D:\\Import";
@SneakyThrows
@Override
public void run() {
log.info("Running file verifier");
// put your code here
}
}
Launcher:
@Service
@Slf4j
public class FileVerifier implements ApplicationRunner {
private final TaskExecutor taskExecutor;
public FileVerifier(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Override
public void run(ApplicationArguments args) {
taskExecutor.execute(new FileVerificationTask());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With