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