简体   繁体   中英

How to start a daemon on server startup in spring

I want to start a daemon mail service thread on tomcat server startup. So, I have annotated a method with @Async annotation.

I have a class which implements a ApplicationListener interface. When I call my async method from this class, it never starts asynchronously and blocks the current thread. And When I call my async method from a spring controller class, It never blocks and starts asynchronously.

Why async method executed successfully from one class and not from the other class?

What am I doing wrong and How can I execute my async method on server startup??

Thanks in advance.

Edit: I tried using the InitializingBean interface, @PostConstruct, init-method approach to call my async method, but it never executed. Then I realized, my default lazy-init is true, So I make the lazy-init to false for my InitializingBean. Now it execute my asnyc method, but it blocks the current thread and now one more issue, I am facing is that My server didn't stop gracefully, but I have to stop my server forcefully.

First of all You don't need to implement ApplicationListener interface. You are working with Spring - Application context is enough.

Second you are talking about Spring @Async , it means that your task should be started from Application Context and Controller bean is a part of it.

You need to make sure that you have <annotation-driven> in your spring xml file.

You can start your task on @PostConstruct function:

@Component
public class SampleBeanImpl implements SampleBean {

  @Async
  void doSomething() { … }
}


@Component
public class SampleBeanInititalizer {

  @Autowired
  private final SampleBean bean;

  @PostConstruct
  public void initialize() {
    bean.doSomething();
  }
}

Based on Spring's reference , use of @Async has limitations during start-up of the application:

@Async can not be used in conjunction with lifecycle callbacks such as @PostConstruct . To asynchronously initialize Spring beans you currently have to use a separate initializing Spring bean that invokes the @Async annotated method on the target then.

So, in your case, maybe it'd be good to have an InitializingBean implementation with your target bean and then start the daemon through that.

Have you added the <annotation-driven> tag to your application context? From the Spring reference doc :

To enable both @Scheduled and @Async annotations, simply include the 'annotation-driven' element from the task namespace in your configuration.

Note, you should also consider to configure an executor instance. From the task schema definition :

Defines a ThreadPoolTaskExecutor instance with configurable pool size, queue-capacity, keep-alive, and rejection-policy values. See Javadoc for the org.springframework.scheduling.annotation.EnableAsync annotation for information on code-based alternatives to this XML element.

So to create an executor that is backed up by a thread pool with 5 threads you have to do the following:

<task:annotation-driven executor="myExecutor"/>
<task:executor id="myExecutor" pool-size="5"/>

For more configuration options, see the @EnableAsync javadoc as stated above.

my english is pool. you must set the Service Class @Lazy(false).

@asyn is something part of spring framework, Does your listener usage spring context? If not, I will suggest to start a new thread in your async method.

I use @PostConstruct with a thread executor

@PostConstruct
public void startServer() {
    final var executorService = Executors.newSingleThreadExecutor();
    executorService.submit(()-> {
      try {

        // make a call to a service that will not stop on it's own
        grpcServer.start().awaitTermination();

      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    });
}

This works with How do you use Spring Boot Actuator using JMX only on a non-web spring boot app

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM