1

How to change the value of cron dynamically after each execution of the method execute

@Component
@EnableScheduling
public class PendingOrderScheduler {

    private final Logger logger;
    private final OrderService orderService;

    public PendingOrderScheduler(Logger logger, OrderService orderService) {
        this.logger = logger;
        this.orderService = orderService;
    }

    @Scheduled(cron = "*/1 * * * * *")
    public void execute() {
        logger.info(String.format("Executed at %s", new Date()));
        this.orderService.updatePendingOrder();
    }
}

2 Answers2

3

I don't think you can use @Scheduled annotation if you want to configure the scheduling of job at runtime.You can use custome scheduler as described in spring documentation.

To change the configuration you need to cancel the current scheduling and create new one using Future object of task scheduler.

Sai prateek
  • 11,842
  • 9
  • 51
  • 66
0

Unfortunately, changing cron inside cron is impossible.

You can use SchedulingConfigurer to achieve this, but @Scheduled annotation will be removed.

@Component
@EnableScheduling
public class PendingOrderScheduler implements SchedulingConfigurer{

    private Map<String,CronTask> cronTasks = new HashMap<>();

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setTaskScheduler(taskScheduler());
        this.taskRegistrar = taskRegistrar;
        addCronTask();
    }

    private CronTask addCronTask(){
        CronTask task = new CronTask(new Runnable() {
            public void run() {
                logger.info(String.format("Executed at %s", new Date()));
                this.orderService.updatePendingOrder();
            }
        }, "*/1 * * * * *"); //read it from some variable
        cronTasks.put("CRON_KEY", task);
        return task;
    }

    public void changeCron(){ //call it when you whant to change chron
        synchronized (PendingOrderScheduler.class) {
            List<CronTask> crons = taskRegistrar.getCronTaskList();
            taskRegistrar.destroy(); //important, cleanups current scheduled tasks
            taskRegistrar.setCronTasksList(new ArrayList<CronTask>());
             for (CronTask cron : crons) {
                if (!cronTasks.containsValue(cron)) {
                    taskRegistrar.addCronTask(cron); //copy croned by @Scheduled tasks as is
                }
            }               
            addCronTask();
            taskRegistrar.afterPropertiesSet(); //rebuild
        }
    }   
}

Also, you can look at Quartz library, which supports cron change.

Ermintar
  • 1,322
  • 3
  • 22
  • 39