Search code examples
javaspring-bootscheduled-tasks

Handling invalid scheduling expression for scheduled task


I have Spring Boot console app with scheduled by cron tasks. Scheduler expression obtained programmatically (can be JSON file or DB). There is a check for the scheduler expression and if it is not valid, it doesn't start scheduled task

Here is a code snippet:

@Service
public class DynamicScheduler implements SchedulingConfigurer {
    private static final Logger _logger = LoggerFactory.getLogger(DynamicScheduler.class);
    @Autowired
    MyTask _myTask; 
    
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(poolScheduler());
        String triggerExpr = getExtressionFromExternal(); //From some source like JSON file or DB
        if (canScheduleTask(triggerExpr)) {
            taskRegistrar.addTriggerTask(() -> scheduleCron(triggerExpr), t -> {
                CronTrigger crontrigger = new CronTrigger(triggerExpr);
                return crontrigger.nextExecution(t);
            });
            
        }
        else { 
            _logger.error("Cannot schedule execution");
        }
    }

    private void scheduleCron(String cron) {
        _myTask.run(); //execute code of the scheduled task
    }
    
    private boolean canScheduleTask(String triggerExpr) {
        //Check if triggerExpr is valid  
    }
    
    @Bean
    public TaskScheduler poolScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
        scheduler.setPoolSize(1);
        scheduler.initialize();
        return scheduler;
    }
}

Currently, if the cron expression is not valid, it will be running with 0 tasks scheduled. Is it possible in this case to exit gracefully from the app or the only possible way to exit by throwing exception?


Solution

  • In Spring boot application, there are many ways to close the application. One such way of closing the application is via ConfigurableApplicationContext. This class object will help in shutting the spring boot application and after then System.exit(0) would help in cleaning the process. Below is the code which helps in stopping the application.

    @Autowired
    private ConfigurableApplicationContext ctx;
    
    
    public void close() {
        int staticExitCode = SpringApplication.exit(ctx, () -> 0);
        System.exit(staticExitCode);
    }
    

    I would also suggest to cleanup other resources using @PreDestroy annotation on method and do the cleanup part.

    @PreDestroy
    public void cleanUp() {
        // Clean up resources, close connections, etc.
        System.out.println("Cleaning up resources before shutdown...");
    }
    

    Spring boot also provide 2 properties for graceful shutdown.

    server.shutdown=graceful
    spring.lifecycle.timeout-per-shutdown-phase=30s
    

    Hope this would help.