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.

shadow-left