DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Calling a Client Via Spring @schedule Cron Job
  • Distributed Task Synchronization: Leveraging ShedLock in Spring
  • External Task Client Implementation in Camunda With Spring Boot Application
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Trending

  • How to Introduce a New API Quickly Using Micronaut
  • Useful System Table Queries in Relational Databases
  • How to Use AWS Aurora Database for a Retail Point of Sale (POS) Transaction System
  • Bridging UI, DevOps, and AI: A Full-Stack Engineer’s Approach to Resilient Systems
  1. DZone
  2. Coding
  3. Frameworks
  4. Dynamically Schedule the Same Task with Multiple Cron Expression Using Spring Boot

Dynamically Schedule the Same Task with Multiple Cron Expression Using Spring Boot

Learn how to schedule a task with multiple cron expressions with Spring Boot and schedule them using ScheduledTaskRegistrar.

By 
Ramesh Silamala user avatar
Ramesh Silamala
·
Apr. 28, 20 · Tutorial
Likes (7)
Comment
Save
Tweet
Share
93.7K Views

Join the DZone community and get the full member experience.

Join For Free

We have seen how to schedule a task within Spring or Spring Boot using a cron expression, with fixed delays. In this in this tutorial, we will see how to schedule a task with multiple cron expressions and change the cron expression on the fly without restarting the server.

Creating a cron trigger task with Spring is pretty easy by adding a @Scheduled annotation to any method and adding @EnableScheduling in any configuration file. But here we use  org.springframework.scheduling.annotation.SchedulingConfigurer  interface . SchedulingConfigurer class has one method,configureTasks(ScheduledTaskRegistrar taskRegistrar) which will be called at the time of bootstrap and register the tasks.

Here, with the help of ScheduledTaskRegistrar, we schedule the task to run at particular time intervals or with fixed rate delays. 

First, we need to implement the SchedulingConfigurer interface where we need to schedule the cron tasks. Refer to the below code to see how to do that.

Java
 




xxxxxxxxxx
1
28
9


 
1
@Configuration
2
@EnableScheduling
3
public class SchedulerConfig implements SchedulingConfigurer {
4
  @Override
5
  public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
6

          
7
    }
8
}


ScheduledTaskRegistrar has multiple override methods to schedule the task. Here I am going to use the   addTriggerTask(Runnable task, Trigger trigger)  which will take Runnable task which we want to schedule and a Trigger at which intervals the task has to be triggered.

ScheduledTaskRegistrar internally implements the InitializingBean so upon creating the bean, it will call the overriden afterProperties method which will start scheduling the added triggered tasks using ScheduledExecutorService and TaskScheduler. See how to add a trigger task using ScheduledTaskRegistrar below.

Java
 




x





1
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
2

          
3
        Runnable runnable = () -> System.out.println("Trigger task executed at " + new Date());
4

          
5
  Trigger trigger = new Trigger() {
6
    @Override
7

          
8
            public Date nextExecutionTime(TriggerContext triggerContext) {
9

          
10
                CronTrigger crontrigger = new CronTrigger("0 0/1 * * * *");
11

          
12
                return crontrigger.nextExecutionTime(triggerContext);
13

          
14
            }
15

          
16
        };
17

          
18
        scheduledTaskRegistrar.addTriggerTask(runnable, trigger);
19

          
20
    }
21

          


With the above code, the runnable task executes at every one minute. 

Now, let's see how to schedule the same task with two or more cron expressions. Here I am taking the list of cron expressions separated with the pipe symbol. In this code, I am running a loop inside the configureTasks to add the trigger for each cron in the list of cron expressions.

Java
 




xxxxxxxxxx
1
29


 
1
String cronsExpressions = "0 0/1 * * * * | 0 0/5 * * * * | 0 0/10 * * * *";
2

          
3
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { 
4

          
5
// Split the cronExpression with pipe and for each expression add the same task.
6
    Stream.of(StringUtils.split(cronsExpressions, "|")).forEache(cronExpression -> { 
7

          
8
         Runnable runnable = () -> System.out.println("Trigger task executed at " + new Date());
9

          
10
                      Trigger trigger = new Trigger() {
11

          
12
                        @Override
13

          
14
                        public Date nextExecutionTime(TriggerContext triggerContext) {
15

          
16
                            CronTrigger crontrigger = new CronTrigger(cronExpression);
17

          
18
                            return crontrigger.nextExecutionTime(triggerContext);
19

          
20
                        }
21

          
22
                    };
23

          
24
               scheduledTaskRegistrar.addTriggerTask(runnable, trigger);
25

          
26
}
27

          
28
}
29

          



With the above code, the runnable task excutes every minute or every 5 or 10 minutes all the time.

Now, to change the task to run at every 2, 7, or 9 minutes all the time and the stop the triggers added for evey 1, 5, or 10 minutes but without having to restart my server. Here the configureTasks will be called during the bootstrap only, but how do we do that now by stopping the existing triggers and creating new trigger task with new cron expressions?

First I will maintain a database property where I will have the cron expression separated by the pipe symbol so that I can change the cron expression on the fly without changing the server.

During the every trigger time I will check the cron expression modified by pulling the cron from data base.

If there is a change in the cron expression, it will stop all the scheduled task and rerun the  configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar)  concurrently again for each of the new cron expression.

Then call the afterProperties  method of  ScheduledTaskRegistrar  to schedule the task with new cron expressions. 

Here when we destroy the existing triggered job it will shutdown the ScheduledExecutorService also, so it is our responsibility to create new ExecutorService and give to  ScheduledTaskRegistrar .

Here is the complete example: 

Java
 




x
1
41


 
1
@Configuration
2
@EnableScheduling
3
public class SchedulerConfig implements SchedulingConfigurer, DisposableBean {
4

          
5
    protected String cronExpressions;
6
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
7
    configDataService // to store the cronexpression in data base so that we can change on the fly when server is running.
8

          
9
    @Override
10
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
11
        cronExpressions = configDataService.getPropertyValue(CRON_EXPRESSIONS);
12
        Stream.of(StringUtils.split(cronExpressions, "|")).forEach(cron -> {
13
            Runnable runnableTask = () -> System.out.println("Task executed at ->" + new Date());
14

          
15
            Trigger trigger = new Trigger() {
16
                @Override
17
                public Date nextExecutionTime(TriggerContext triggerContext) {
18
                    String newCronExpression = configDataService.getPropertyValue(CRON_EXPRESSIONS);
19
                    if (!StringUtils.equalsAnyIgnoreCase(newCronExpression, cronExpressions)) {
20
                        taskRegistrar.setTriggerTasksList(new ArrayList<TriggerTask>());
21
                        configureTasks(taskRegistrar); // calling recursively.
22
                        taskRegistrar.destroy(); // destroys previously scheduled tasks.
23
                        taskRegistrar.setScheduler(executor);
24
                        taskRegistrar.afterPropertiesSet(); // this will schedule the task with new cron changes.
25
                        return null; // return null when the cron changed so the trigger will stop.
26
                    }
27
                    CronTrigger crontrigger = new CronTrigger(cron);
28
                    return crontrigger.nextExecutionTime(triggerContext);
29
                }
30
            };
31
            taskRegistrar.addTriggerTask(runnable, trigger);
32
        });
33
    }
34

          
35
    @Override
36
    public void destroy() throws Exception {
37
        if (executor != null) {
38
            executor.shutdownNow();
39
        }
40
    }
41
}



Always make sure to shut down any executor services that you create.

Please comment here if you see any issues or if you have any suggestions.

Spring Framework Task (computing) Crons Spring Boot Schedule (computer science)

Opinions expressed by DZone contributors are their own.

Related

  • Calling a Client Via Spring @schedule Cron Job
  • Distributed Task Synchronization: Leveraging ShedLock in Spring
  • External Task Client Implementation in Camunda With Spring Boot Application
  • Actuator Enhancements: Spring Framework 6.2 and Spring Boot 3.4

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!