How to dynamically turn on/off a scheduled method in a springboot application

Sumit picture Sumit · Jun 9, 2017 · Viewed 8.9k times · Source

I am building a Springboot application and I want to turn on a scheduled method from the front-end. (as in I want the scheduler to run only after the method is called from the front-end)

This scheduled method will then call a web-service with the given parameter and keep on running until a specific response ("Success") is received.

Once the specific response is received, I want the scheduled method to stop running until it is called again from the front end.

I am not sure how to start and stop the execution of the scheduled method.

I have this currently:

@Component
public class ScheduledTasks {

    private static final Logger LOG = LoggerFactory.getLogger(ScheduledTasks.class);

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    @Scheduled(fixedRate = 5000)
    public void waitForSuccess(String componentName) {
        LOG.info("Running at: " + dateFormat.format(new Date()));
        String response = MyWebService.checkStatus(componentName);
        if ("success".equalsIgnoreCase(response)) {
            LOG.info("success");
            //Stop scheduling this method
        } else {
            LOG.info("keep waiting");
        }
    }
}

Here is my controller through which the scheduled method is to be turned on:

@Controller
public class MainController {

    @GetMapping(/start/{componentName})
    public @ResponseBody String startExecution(@PathVariable String componentName) {
        //do some other stuff
        //start scheduling the scheduled method with the parameter 'componentName'
        System.out.println("Waiting for response");
    }

}

Is my approach correct? How can I achieve this functionality using springboot and schedulers?

Answer

Maksym Pecheniuk picture Maksym Pecheniuk · Sep 27, 2017

Here is the full example of start/stop API for 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());
    }

}