I am writing spring boot app with ThreadPoolTaskExecutor. Here is my Application class:
import info.gandraweb.apns.service.MessageService;
import info.gandraweb.apns.settings.AppSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@SpringBootApplication
@EnableScheduling
@EnableAutoConfiguration
@EnableAsync
public class Application implements AsyncConfigurer{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private AppSettings appSettings;
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
AppSettings appSettings = applicationContext.getBean(AppSettings.class);
logger.info(appSettings.toString());
test(applicationContext);
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setThreadNamePrefix("MyExecutor-");
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(50);
taskExecutor.setQueueCapacity(1000);
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
private static void test(ApplicationContext applicationContext) {
MessageService messageService = applicationContext.getBean(MessageService.class);
messageService.processNewMessages();
}
}**
inside test method I am calling
messageService.processNewMessages()
which, in turn, if exists some task in DB call Async method on another bean to process it.
When there is no tasks for processing app finishes.
If there are any tasks in DB for processing after execution app keep running and never finish .... seems like shutdown() method on ThreadPoolTaskExecutor is never called?
Then I have implemented ApplicationListener interface and logged what is going on inside onApplicationEvent(ContextClosedEvent)
So when there is no task for processing app finish and ContextClosedEvent is triggered. If there are any tasks in DB for processing after execution ContextClosedEvent is not triggered???
When I remove AsyncConfigurer from app then ContextClosedEvent is trigered and app is shutdown. But in such case I have lost posibility to configure ThreadPoolTaskExecutor.
So, how I can configure ThreadPoolTaskExecutor and manage to gracefully shutdown this executor, or to trigger ContextClosedEvent ... whatever is preferred way to gracefully shutdown it?