Is there a way to start or stop a task scheduled using Spring Scheduled Tasks initialized using context file or @Scheduled annotation?
I would like to start the task when required and stop it when the task is no longer needed to be run.
If this is not possible, any alternative to injecting spring variables to a thread?
Here is an example of starting/stopping a scheduled method in Spring Boot. You can use such APIs:
http:localhost:8080/start - for starting scheduled method with fixed rate 5000 ms
http:localhost:8080/stop - for stopping scheduled method
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.time.Instant;
import java.util.concurrent.ScheduledFuture;
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class TaskSchedulingApplication {
public static void main(String[] args) {
SpringApplication.run(TaskSchedulingApplication.class, args);
}
@Bean
TaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}
@Controller
class ScheduleController {
public static final long FIXED_RATE = 5000;
@Autowired
TaskScheduler taskScheduler;
ScheduledFuture<?> scheduledFuture;
@RequestMapping("start")
ResponseEntity<Void> start() {
scheduledFuture = taskScheduler.scheduleAtFixedRate(printHour(), FIXED_RATE);
return new ResponseEntity<Void>(HttpStatus.OK);
}
@RequestMapping("stop")
ResponseEntity<Void> stop() {
scheduledFuture.cancel(false);
return new ResponseEntity<Void>(HttpStatus.OK);
}
private Runnable printHour() {
return () -> System.out.println("Hello " + Instant.now().toEpochMilli());
}
}
Stopping registered @Scheduled beans is not standard feature since the access to them is private in the org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor
.
If you need to manage the time they run you need to register them programmatically (TriggerTask
): see the documentation to org.springframework.scheduling.annotation.SchedulingConfigurer
. In the type org.springframework.scheduling.config.TriggerTask
there is the method which returns type of org.springframework.scheduling.Trigger
. There you can manage next execution time.
TriggerTask
s could be beans in the case of programmatical registration.
Have the @Scheduled
method look for a variable held in Application
state or ServletContext
, or from a value stored in the DB. If the value is TRUE, proceed with the task; if FALSE, don't start. This setup will control the scheduled run.
If you want to also be able to fire the task at will, reference the task's method from a Controller; that way you can fire it at will. Additionally, if its a longer running task, create a second method annotated @Async
and call that method from your Controller so that it runs in its own thread.
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