5

I have a spring scheduler which has three tasks with different triggers(cron triggers). For each of those tasks, I have a UI which can modify the cron expression. I want to reschedule the tasks when the service receives the request to update. Below is my Scheduler configuratin. How can I change the schedule of one of the tasks at runtime(When UI sends the request to update the cron expression in the DB). With the below approach, the scheduler is only updated with the next schedule. i.e. the nextExecutionTime() method is called when the trigger is called.

@Configuration
@EnableScheduling
public class Config implements SchedulingConfigurer {

    @Inject
    MyDao db;
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);

        List<TaskConfig> conf = db.readTaks();
        conf.forEach((TaskConfig aTask) -> {
            taskRegistrar.addTriggerTask(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Running task + " + aTask.getName());
                }
            }, new Trigger() {
                @Override
                public Date nextExecutionTime(final TriggerContext triggerContext) {
                    String expression = aTask.getCronExpression();
                    CronTrigger trigger = new CronTrigger(expression);
                    Date nextExec = trigger.nextExecutionTime(triggerContext);
                    return nextExec;
                }
            });
        });
    }
}

Edit: Eg. Consider my cron expression is set to trigger initially at 40th minute of every hour and the current time is 11:20 AM. Now, if I update the cron now to trigger at 25th minute, I expect the task to be trigger at 11:25 AM. But with the above code it triggers at 11:40AM and then triggers at 12:25PM. This is not the behavior I want.

pravat
  • 465
  • 3
  • 11
  • Possible duplicate of [How to change Spring's @Scheduled fixedDelay at runtime](https://stackoverflow.com/questions/15250928/how-to-change-springs-scheduled-fixeddelay-at-runtime) – Abhijit Sarkar Jul 14 '17 at 20:53
  • Nope. I kind of do similar thing here. But the issue is the trigger is updated only when the nextExecution time is called. Will update the question with an example. – pravat Jul 14 '17 at 22:00
  • Did you get a proper solution for this? – GauthamK Apr 09 '21 at 06:18

1 Answers1

1

I think you have 2 options:

  1. Refresh the context; this will work assuming you updated the database so that db.readTaks() returns the updated schedule.
  2. Add a trigger with the new time, to be executed once. This can be done by injecting the ScheduledTaskRegistrar, and adding a trigger for 11:25am like in your example. Here's a crude example:

    @Autowired
    private ScheduledTaskRegistrar taskRegistrar;
    
    void runOnce() {
        taskRegistrar.scheduleCronTask(task);
    }
    
Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • Option 1: Do you mean the application context? That would be terrible. If there a way to refresh the scheduler only?? Option 2: I like the idea. It would trigger at the 25th minute. But the existing scheduler would still trigger the task at the 50th minute before updating itself. Isn't it? – pravat Jul 17 '17 at 18:58
  • @pravat 1. Regular Spring beans can't do that; see [RefreshScope](http://cloud.spring.io/spring-cloud-static/docs/1.0.x/spring-cloud.html#_refresh_scope). 2. Yes, in this case, you're not disrupting the existing schedule, just adding a new ad hoc job. – Abhijit Sarkar Jul 17 '17 at 19:10