Spring boot schedule for dynamic multiple cron expression

727 Views Asked by At

Friends, I have one requirement where client can schedule a job weekly and he can change this value anytime and without restart application it should have new changes applicable. And application will be used by many clients hence there will be multiple dynamic schedulers and each will run based on its configuration. Example -

Customer1 schedules Job on Monday 1:00PM 
Customer2 schedules Job on Wednesday 3:00AM

I need to write Sprint boot scheduler which can take this values from data base dynamically. Assume this started running properly, and Customer1 changes Job timing to

Customer1 reschedules Job on Friday 1:00PM

then application should have this changes applicable. I am able to get value from data base and able to run it dynamically. However, when customer changes values then how to retrigger Job without restarting application. I have gone through few links but want a feasible solution as I don't get it.

What I have done

@SpringBootApplication
@EnableScheduling
@EnableAsync
@EnableConfigurationProperties
public class PricingApplication extends SpringBootServletInitializer implements SchedulingConfigurer, DisposableBean {


    ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    public static void main(String[] args) {
        SpringApplication.run(PricingApplication.class, args);
    }
        
    
    public Map<Long, String> myCustomScheduler(){
     // Hard coded below values but actually it will populate from DB and cron expression will get as below
        Map<Long, String> cronSchedule = new HashMap<>();
        cronSchedule.put(1L, "*/25 * * * * *");
        cronSchedule.put(2L, "*/5 * * * * *");
        return cronSchedule;
    }


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar){
        Map<Long, String> cronValues =  myCustomScheduler();

        cronValues.forEach((customer, cronValue) ->{
            Runnable runTask = () -> System.out.println("This is the task scheduled for customer - "+customer+ "  Ans cron Expression is "+cronValue);
            Trigger trigger = new Trigger() {
                @Override
                public Date nextExecutionTime(TriggerContext triggerContext) {
                    Map<Long, String> newCronValues = myCustomScheduler();
                    String newCron = newCronValues.get(customer);
                    if(!newCron.equalsIgnoreCase(cronValue)){
                        taskRegistrar.setTriggerTasksList(new ArrayList<TriggerTask>());
                        configureTasks(taskRegistrar);
                        taskRegistrar.destroy();
                        taskRegistrar.setScheduler(scheduledExecutorService);
                        taskRegistrar.afterPropertiesSet();
                        return  null;
                    }
                    CronTrigger cronTrigger = new CronTrigger(cronValue);
                    return cronTrigger.nextExecutionTime(triggerContext);
                }
            };
            taskRegistrar.addTriggerTask(runTask, trigger);
        });
    }

   

    @Override
    public void destroy() throws Exception {
        if (scheduledExecutorService != null) {
            scheduledExecutorService.shutdownNow();
        }
    }
}

Any suggestion or best approach to handle above situation. Appreciated any response here

0

There are 0 best solutions below