Dynamic Scheduling with Spring Boot

We can achieve scheduling in many ways, in here we will talk about how we can achieve it in both Static and Dynamic ways using Spring Boot.
So first we will see the Static part.

  1. Static Scheduling using “@Scheduled” annotation.
    You must be wondering why this guy is calling static again and again, it’s just scheduling, isn’t it? No its not!
    I am mentioning it static because we have to hardcode the interval in respective scheduled classes to use the @Scheduled annotation in your spring application you need to let know your spring boot starter class that,
    we are using the scheduling in here.
    in simple words mark your starter class with @EnableScheduling

    @EnableScheduling
    public class SpringConfig {
    ...
    }
    It enables Spring's scheduled task execution capability.

    Schedule task at a fixed rate

    @Scheduled(initialDelay = 1000, fixedRate = 10000)
     public void run() {
         logger.info("Current time is :: " + Calendar.getInstance().getTime());
     }
    

    Output :

    2019-03-03 15:02:55 - Current time is :: Sun Mar 03 15:02:55 IST2019 2019-03-03 15:03:05 - Current time is :: Sun Mar 03 15:03:05 IST 2019 2019-03-03 15:03:15 - Current time is :: Sun Mar 03 15:03:15 IST 2019 2019-03-03 15:03:25 - Current time is :: Sun Mar 03 15:03:25 IST 2019 2019-03-03 15:03:35 - Current time is :: Sun Mar 03 15:03:35 IST 2019

    Schedule task at a fixed delay

    It will run the configured tasks after a fixed delay.
    In the following example, the task is running after every 10 secs.

    @Scheduled(fixedDelay = 10000)
     public void run() {
         logger.info("Current time is :: " + Calendar.getInstance().getTime());
    }

    Schedule task using CRON expression

    We can also provide CRON expression in @Scheduled annotation.

    @Scheduled(cron = "0 10 10 10 * ?")
     public void run() {
         logger.info("Current time is :: " + Calendar.getInstance().getTime());
     }

    Now Consider a scenario where business demands to run the defined task inflexible manner.
    Let’s suppose I want to execute it more frequently in the day time and less in the night so that my server should run more efficiently.
    Every time we can’t go and change the interval in code, That’s not the feasible solution.

    Great !! that’s where our so-called Dynamic scheduling part comes into the picture.

  2. Dynamic Scheduling using “SchedularConfigurer” interface.
    A Background :
    I came across this because we had a requirement to run the schedule flexibility, let’s suppose I am writing a scheduler for a bank to process notifications, which are generated by another application and all notifications to be sent are kept under one table, and they will be picked up by the scheduler. Now notification processing frequency is high between morning 9 am to 2 PM and moderate after that.
    so I will set a frequency of schedule as it suits me.If we go the static one we can’t control this dynamic behavior, at that time we can leverage the SchedularConfigurer interface

    We are using Spring’s SchedularConfigurer functional interface.
    it came into the existence after version Spring 5+ onwards.

    Code Examples are given below.

    @Configuration
    public class MyJob 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;
       }
    }

it will fetch the next execution time every time it gets triggered as per the previous job scheduled.

As given in the code we can fetch or check for the interval is changed or not using the getNewExecutionTime() method.

You can get the code from GitHub link

Happy Learning !!

3 comments

  1. For the section 2., could you give advice for my case is: get the new execution time from DB, for instance I get a list of java.time Instant to execute a job, how could we write the configureTasks()? Thank you!

    Like

Leave a comment