Spicy Spring : Scheduler does not shutdown
On my current project we use Java 8, Spring 4.3 and Tomcat 7.0 as application server.
After the scheduling functionality was added to the project the application server did not shut down any more, it hung till the end of time.
I like to use the default Java implementations when possible so the configured scheduler was the java.util.concurrent.ScheduledThreadPoolExecutor
.
package com.jdriven.blog.mib.scheduler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@Configuration
@EnableScheduling
public class SchedulingConfig1 implements SchedulingConfigurer {
@Value("${scheduler.pool.size:10}")
private Integer poolSize;
/**
* To configure the task executer
*
* @param taskRegistrar the scheduled task registrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
/**
* @return executor for the scheduler (naming convention)
*/
@Bean(name = "taskScheduler", destroyMethod = "shutdown")
public Executor taskExecutor() {
// create a default java thread pool executor
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(poolSize);
return scheduledExecutorService;
}
}
After some investigation we found out that the application server did not shutdown because the created ScheduledExecutorService
bean did not stop.
The threads in the thread pool didn’t stop when the application context is destroyed.
The destroyMethod is defined and Spring calls the shutdown method but it still did not stop the application server.
When I tested with Spring Boot it shuts down without a problem. Spring has also their own ThreadPoolTaskScheduler
with much more configuration options.
Strangely it does not implement the same interface java.util.concurrent.ScheduledExecutorService
as I would expect from the Spring framework but you can use both implementations.
package com.jdriven.blog.mib.scheduler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
@Configuration
@EnableScheduling
public class SchedulingConfig2 implements SchedulingConfigurer {
@Value("${scheduler.pool.size:10}")
private Integer poolSize;
/**
* To configure the task executer
*
* @param taskRegistrar the scheduled task registrar
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
/**
* @return executor for the scheduler (naming convention)
*/
@Bean(name = "taskScheduler", destroyMethod = "shutdown")
public Executor taskExecutor() {
// use the Spring ThreadPoolTaskScheduler
ThreadPoolTaskScheduler scheduledExecutorService = new ThreadPoolTaskScheduler();
// always set the poolsize
scheduledExecutorService.setPoolSize(poolSize);
// for logging add a threadNamePrefix
scheduledExecutorService.setThreadNamePrefix("myTaskScheduler-");
// do not wait for completion of the task
scheduledExecutorService.setWaitForTasksToCompleteOnShutdown(false);
return scheduledExecutorService;
}
}
With the Spring ThreadPoolTaskScheduler
the application server does shutdown.