Scheduling a job with Spring programmatically (with fixedRate set dynamically) Scheduling a job with Spring programmatically (with fixedRate set dynamically) java java

Scheduling a job with Spring programmatically (with fixedRate set dynamically)


Using a Trigger you can calculate the next execution time on the fly.

Something like this should do the trick (adapted from the Javadoc for @EnableScheduling):

@Configuration@EnableSchedulingpublic class MyAppConfig implements SchedulingConfigurer {    @Autowired    Environment env;    @Bean    public MyBean myBean() {        return new MyBean();    }    @Bean(destroyMethod = "shutdown")    public Executor taskExecutor() {        return Executors.newScheduledThreadPool(100);    }    @Override    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {        taskRegistrar.setScheduler(taskExecutor());        taskRegistrar.addTriggerTask(                new Runnable() {                    @Override public void run() {                        myBean().getSchedule();                    }                },                new Trigger() {                    @Override public Date nextExecutionTime(TriggerContext triggerContext) {                        Calendar nextExecutionTime =  new GregorianCalendar();                        Date lastActualExecutionTime = triggerContext.lastActualExecutionTime();                        nextExecutionTime.setTime(lastActualExecutionTime != null ? lastActualExecutionTime : new Date());                        nextExecutionTime.add(Calendar.MILLISECOND, env.getProperty("myRate", Integer.class)); //you can get the value from wherever you want                        return nextExecutionTime.getTime();                    }                }        );    }}


You can also use Spring Expression Language (SpEL) for this.

Once this value is initialized, you won't be able to update this value.

@Scheduled(fixedRateString = "#{@applicationPropertyService.getApplicationProperty()}")public void getSchedule(){   System.out.println("in scheduled job");}@Servicepublic class ApplicationPropertyService {    public String getApplicationProperty(){        //get your value here        return "5000";    }}


To create and manage multiple dynamically scheduled tasks,

Schedular configuration and bean:

import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.Trigger;import org.springframework.scheduling.TriggerContext;import org.springframework.scheduling.annotation.SchedulingConfigurer;import org.springframework.scheduling.config.ScheduledTaskRegistrar;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;@Configuration@EnableSchedulingpublic class SchedulingConfigs implements SchedulingConfigurer {    @Override    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {        taskRegistrar.addTriggerTask(new Runnable() {            @Override            public void run() {                // Do not put @Scheduled annotation above this method, we don't need it anymore.                System.out.println("Running Schedular..." + Calendar.getInstance().getTime());            }        }, new Trigger() {            @Override            public Date nextExecutionTime(TriggerContext triggerContext) {                Calendar nextExecutionTime = new GregorianCalendar();                Date lastActualExecutionTime = triggerContext.lastActualExecutionTime();                nextExecutionTime.setTime(lastActualExecutionTime != null ? lastActualExecutionTime : new Date());                nextExecutionTime.add(Calendar.MILLISECOND, getNewExecutionTime());                return nextExecutionTime.getTime();            }        });    }    private int getNewExecutionTime() {        //Load Your execution time from database or property file        return 1000;    }    @Bean    public TaskScheduler poolScheduler() {        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();        scheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");        scheduler.setPoolSize(1);        scheduler.initialize();        return scheduler;    }}

Scheduler service code:

package io.loadium.resource.service;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.context.event.EventListener;import org.springframework.scheduling.TaskScheduler;import org.springframework.stereotype.Service;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ScheduledFuture;@Servicepublic class ScheduleTaskService {    // Task Scheduler    TaskScheduler scheduler;    // A map for keeping scheduled tasks    Map<Integer, ScheduledFuture<?>> jobsMap = new HashMap<>();    public ScheduleTaskService(TaskScheduler scheduler) {        this.scheduler = scheduler;    }    // Schedule Task to be executed every night at 00 or 12 am    public void addTaskToScheduler(int id, Runnable task, Date runningDate) {        ScheduledFuture<?> scheduledTask = scheduler.schedule(task, runningDate);        jobsMap.put(id, scheduledTask);    }    // Remove scheduled task    public void removeTaskFromScheduler(int id) {        ScheduledFuture<?> scheduledTask = jobsMap.get(id);        if (scheduledTask != null) {            scheduledTask.cancel(true);            jobsMap.put(id, null);        }    }    // A context refresh event listener    @EventListener({ContextRefreshedEvent.class})    void contextRefreshedEvent() {        // Get all tasks from DB and reschedule them in case of context restarted    }}

Sample usage:

// Add a new task with runtime after 10 secondsscheduleTaskService.addTaskToScheduler(1, () -> System.out.println("my task is running -> 1"), , Date.from(LocalDateTime.now().plusSeconds(10).atZone(ZoneId.systemDefault()).toInstant()));// Remove scheduled taskscheduleTaskService.removeTaskFromScheduler(1);