Не удается запустить несколько методов последовательно при запуске Spring Boot

#spring #spring-boot #netty #startup #autostart

#spring #spring-boot #netty #запуск #автозапуск

Вопрос:

Я должен запустить несколько методов при запуске приложения, например, следующее:

 @SpringBootApplication
public class Application implements CommandLineRunner {

    private final MonitoringService monitoringService;
    private final QrReaderServer qrReaderServer;

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

Однако выполняется только первый! И приложение запускается:

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

Второй всегда пропускается!

Если изменить порядок вызовов — будет выполнен только второй.

Не удалось найти никакого решения для запуска обоих в начале — попробовал @PostConstruct , ApplicationRunner @EventListener(ApplicationReadyEvent.class)

Похоже, они каким-то образом блокируют друг друга. Несмотря на то, что оба имеют тип void.

Мониторинг реализации запуска:

 @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 (запуск TCP-сервера с конфигурацией Netty):

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

Как решить эту проблему?

Ответ №1:

Запуск launchMonitoring() асинхронно.

Самый простой способ сделать это — включить асинхронность, добавив @EnableAsync в ваше приложение, а затем аннотировать launchMonitoring() с помощью @Async

Не уверен, что launchServer() следует также запускать асинхронно.

РЕДАКТИРОВАТЬ: завершенный ответ

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

По умолчанию Spring создаст SimpleAsyncTaskExecutor , но вы можете предоставить свой TaskExecutor

Пример:

  @EnableAsync
 @Configuration
 public class AsyncConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.set... // your custom configs
         executor.initialize();
         return executor;
     }

    ...
 }
  

Комментарии:

1. make only launchMonitoring() — и это работает как очаровательный

2. Обнаружен какой-то странный сбой в журнале No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either . Нужно ли мне добавить какой-либо исполнитель задачи? Пока все работает нормально.

3. @nazar_art завершите мой ответ

4. Я установил имя потока для AsyncConfig carpark-ex-1 4 начальных потоков. И посмотрите, что это всегда выполняется только с одним потоком carpark-ex-1 . Нужно ли мне создавать этот компонент с областью прототипа для выполнения с несколькими потоками?

5. почему вы должны хотеть выполняться launchMonitoring() с несколькими потоками?