I have created a simple scheduled task using Spring Framework's @Scheduled
annotation.
@Scheduled(fixedRate = 2000) public void doSomething() {}
Now I want to stop this task, when no longer needed.
I know there could be one alternative to check one conditional flag at the start of this method, but this will not stop execution of this method.
Is there anything Spring provides to stop @Scheduled
task ?
Canceling the Scheduled Future. Another way to stop the scheduler would be manually canceling its Future. In the cases with multiple scheduler tasks, then we can maintain the Future map inside of the custom scheduler pool but cancel the corresponding scheduled Future based on scheduler class.
The cancel() method is used to cancel the timer task. The cancel() methods returns true when the task is scheduled for one-time execution and has not executed until now and returns false when the task was scheduled for one-time execution and has been executed already.
Supply ScheduledAnnotationBeanPostProcessor
and explicitly invoke postProcessBeforeDestruction(Object bean, String beanName)
, for the bean whose scheduling should be stopped.
private final Map<Object, ScheduledFuture<?>> scheduledTasks = new IdentityHashMap<>(); @Scheduled(fixedRate = 2000) public void fixedRateJob() { System.out.println("Something to be done every 2 secs"); } @Bean public TaskScheduler poolScheduler() { return new CustomTaskScheduler(); } class CustomTaskScheduler extends ThreadPoolTaskScheduler { @Override public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) { ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period); ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task; scheduledTasks.put(runnable.getTarget(), future); return future; } @Override public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) { ScheduledFuture<?> future = super.scheduleAtFixedRate(task, startTime, period); ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task; scheduledTasks.put(runnable.getTarget(), future); return future; } }
When the scheduling for a bean has to be stopped, you can lookup the map to get the corresponding Future
to it and explicitly cancel it.
Here is an example where we can stop , start , and list also all the scheduled running tasks:
@RestController @RequestMapping("/test") public class TestController { private static final String SCHEDULED_TASKS = "scheduledTasks"; @Autowired private ScheduledAnnotationBeanPostProcessor postProcessor; @Autowired private ScheduledTasks scheduledTasks; @Autowired private ObjectMapper objectMapper; @GetMapping(value = "/stopScheduler") public String stopSchedule(){ postProcessor.postProcessBeforeDestruction(scheduledTasks, SCHEDULED_TASKS); return "OK"; } @GetMapping(value = "/startScheduler") public String startSchedule(){ postProcessor.postProcessAfterInitialization(scheduledTasks, SCHEDULED_TASKS); return "OK"; } @GetMapping(value = "/listScheduler") public String listSchedules() throws JsonProcessingException{ Set<ScheduledTask> setTasks = postProcessor.getScheduledTasks(); if(!setTasks.isEmpty()){ return objectMapper.writeValueAsString(setTasks); }else{ return "No running tasks !"; } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With