Search code examples
springspring-bootnettystartupautostart

Can not run few methods sequentially when Spring Boot starts


I have to run a few methods when Application starts, like the following:

@SpringBootApplication
public class Application implements CommandLineRunner {

    private final MonitoringService monitoringService;
    private final QrReaderServer qrReaderServer;

    @Override
    public void run(String... args) {
        monitoringService.launchMonitoring();
        qrReaderServer.launchServer();
    }

However, only the first one is executed! And the application is started:

... Started Application in 5.21 seconds (JVM running for 6.336)
... START_MONITORING for folder: D:\results

The second one is always skipped!

If change the call order - the only the second one will be executed.

Could not find any solution for launching both at the beginning - tried @PostConstruct, ApplicationRunner, @EventListener(ApplicationReadyEvent.class)...

Looks like they are blocking each other somehow. Despite the fact that both have void type.

Monitoring launch implementation:

@Override
public void launchMonitoring() {
    log.info("START_MONITORING for folder: {}", monitoringProperties.getFolder());
    try {
        WatchKey key;
        while ((key = watchService.take()) != null) {
            for (WatchEvent<?> event : key.pollEvents()) {

                WatchEvent.Kind<?> kind = event.kind();

                if (kind == ENTRY_CREATE) {
                    log.info("FILE_CREATED: {}", event.context());

                    // some delay for fully file upload
                    Thread.sleep(monitoringProperties.getFrequency());

                    String fullFileName = getFileName(event);
                    String fileName = FilenameUtils.removeExtension(fullFileName);

                    processResource(fullFileName, fileName);
                }
            }
            key.reset();
        }
    } catch (InterruptedException e) {
        log.error("interrupted exception for monitoring service", e);
    } catch (IOException e) {
        log.error("io exception while processing file", e);
    } 
}

QR Reader start (launch TCP server with Netty configuration):

@Override
public void launchServer() {
    try {
        ChannelFuture serverChannelFuture = serverBootstrap.bind(hostAddress).sync();
        log.info("Server is STARTED : port {}", hostAddress.getPort());

        serverChannel = serverChannelFuture.channel().closeFuture().sync().channel();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        shutdownQuietly();
    }
}

How to solve this issue?


Solution

  • Start launchMonitoring() asynchronously.

    The easiest way to do this is to enable Async by adding @EnableAsync on your Application and then annotate launchMonitoring() with @Async

    Not sure if launchServer() should also be started asynchronously.

    EDIT: completed Answer

    No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either

    By default Spring will create a SimpleAsyncTaskExecutor, but you can provide your taskExecutor

    Example:

     @EnableAsync
     @Configuration
     public class AsyncConfig implements AsyncConfigurer {
    
         @Override
         public Executor getAsyncExecutor() {
             ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
             executor.set... // your custom configs
             executor.initialize();
             return executor;
         }
    
        ...
     }