Search code examples
javaspring-bootquartz-schedulertomcat8

Spring boot @Scheduler not working on tomcat


I have a @Scheduled method which runs without a problem when I build my Spring Boot application using embedded tomcat. But when i build my project in .war and deploy it using tomcat v8, it seem like scheduler not trigger. Other functions working great just this scheduler not trigger on my server.

@Component
public class DeleteUser {

@Autowired
private UserService userService;

@Autowired
private UserAuthoritiesService userAuthService;

private static final Logger logger = LoggerFactory.getLogger(DeleteUser.class);

private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

//(cron="second, minute, hour, day of month, month, day(s) of week")
@Scheduled(cron="0 0 8 * * *", zone="Asia/Kuala_Lumpur")
public void schedulerDeleteUser() {

    List<User> ls = userService.getAllInactiveUser3Day(new Date());

    try {
        if(ls.size()>0) {

            for(User user: ls) {
                userService.updateStatusAccount(false, user.getId());
            }
        }
    }
    catch(Exception e) {
        logger.error(e.getMessage());
    }
    logger.info("Scheduler run at {}", dateFormat.format(new Date()));
  }
}

Solution

  • I had the same problem: everything working fine on built-in tomcat server but not when I've deployed .war file into production. I've tried a few things to solve it (don't remember exactly which particular one worked) and eventually I've ended up with the following:

    1. I have dedicated scheduler configuration class:

      @Configuration
      @EnableScheduling
      @EnableAsync
      public class SchedulerConfiguration implements SchedulingConfigurer {
      
          private final int POOL_SIZE = 2;
          private final String THREAD_NAME_PREFIX = "task-scheduler-";
      
          @Override
          public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
              ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
      
              threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
              threadPoolTaskScheduler.setThreadNamePrefix(THREAD_NAME_PREFIX);
              threadPoolTaskScheduler.initialize();
      
              scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
          }
      }
      

      I guess, what's most important above are @EnableScheduling and @EnableAsync annotations (I didn't had the 2nd one before)

    2. Last but not least, I have noticed that my main application class wasn't extending SpringBootServletInitializer so I have fixed that too:

      public class SpringBootApplication extends SpringBootServletInitializer {
          public static void main(String[] args) {
              SpringApplication.run(MarketplaceMonitorApplication.class, args);
          }
      }
      

      Without it, application started but @Scheduling wasn't working.. or I fixed that earlier and forget :-) Anyway, please make sure you have it! ;-)

    Now everything works on the production as expected.