Spring Scheduler Example

0

In this article we will see how to use spring scheduler framework to execute a task at some fixed intervals. You can either configure it using task namespace in XML or using the Spring provided annotation support for task scheduling. We will see how with just few annotations we can schedule a task.

@EnableScheduling Annotation

Spring enables scheduling task execution using @EnableScheduling annotation. Once included spring will automatically register an internal bean post processor which in turn detects @Scheduled annotated methods on a spring managed bean.

After the bean gets initialized, the bean processor kicks in to register all the @Scheduled annotated methods defined in the bean’s target class.

In the below @Configuration annotated class, we define a @Scheduled method with fixedDelay set to 2000 milliseconds. Spring will invoke the task , after the completion of one execution and the start of the next, it will wait for the fixed delay specified. If an initial delay is specified then the start time of the execution will be the current time plus the initial delay.

SpringEnableSchedulingExample:

package com.javarticles.spring;

import java.util.Date;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SpringEnableSchedulingExample {

    @Scheduled(fixedDelay = 2000)
    public void executeEveryOneMin() {
        System.out.println("Run Job " + new Date());
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                SpringEnableSchedulingExample.class);
        String scheduledAnnotationProcessor = "org.springframework.context.annotation.internalScheduledAnnotationProcessor";
        System.out.println("Contains " + scheduledAnnotationProcessor + ": "
                + context.containsBean(scheduledAnnotationProcessor));
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.close();
        }
    }
}

Output:

May 14, 2016 9:05:43 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:05:43 IST 2016]; root of context hierarchy
Run Job Sat May 14 09:05:44 IST 2016
Contains org.springframework.context.annotation.internalScheduledAnnotationProcessor: true
Run Job Sat May 14 09:05:46 IST 2016
Run Job Sat May 14 09:05:48 IST 2016
Run Job Sat May 14 09:05:50 IST 2016
Run Job Sat May 14 09:05:52 IST 2016
May 14, 2016 9:05:52 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:05:43 IST 2016]; root of context hierarchy

Spring Scheduling using XML

The @Scheduled annotation bean processor is responsible to register the @Scheduled annotated methods. We have seen how we can enable scheduling using @EnableScheduling annotation. In this example, we will see how we can enable scheduling using spring XML configuration. We just need to add <task:annotation-driven /> and this in turn will register the bean post processor ScheduledAnnotationBeanPostProcessor.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">

	<task:annotation-driven />
	<bean class="com.javarticles.spring.SpringSchedulingEnabledViaXMLExample" />
</beans>

SpringSchedulingEnabledViaXMLExample:

package com.javarticles.spring;

import java.util.Date;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;

public class SpringSchedulingEnabledViaXMLExample {

    @Scheduled(fixedDelay = 2000)
    public void executeEveryOneMin() {
        System.out.println("Run Job " + new Date());
    }

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        String scheduledAnnotationProcessor = "org.springframework.context.annotation.internalScheduledAnnotationProcessor";
        System.out.println("Contains " + scheduledAnnotationProcessor + ": "
                + context.containsBean(scheduledAnnotationProcessor));
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.close();
        }
    }
}

Output:

May 14, 2016 9:09:32 AM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContex[email protected]: startup date [Sat May 14 09:09:32 IST 2016]; root of context hierarchy
May 14, 2016 9:09:32 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
Run Job Sat May 14 09:09:33 IST 2016
Contains org.springframework.context.annotation.internalScheduledAnnotationProcessor: true
Run Job Sat May 14 09:09:35 IST 2016
Run Job Sat May 14 09:09:37 IST 2016
Run Job Sat May 14 09:09:39 IST 2016
Run Job Sat May 14 09:09:41 IST 2016May 14, 2016 9:09:41 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContex[email protected]: startup date [Sat May 14 09:09:32 IST 2016]; root of context hierarchy
There are three main attributes that help us in scheduling a task fixedDelay, fixedRate and cron.

Spring Scheduler with fixed delay

fixedDelay specifies the delay between the completion of one execution and the start of the next. As you can see in the below diagram, the next invocation starts only after waiting for the fixed delay specified in the annotation attribute.

Spring Scheduler Fixed Delay

Spring Scheduler Fixed Delay

SpringScheduleFixedDelayExample:

package com.javarticles.spring;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SpringScheduleFixedDelayExample {
    private AtomicInteger counter = new AtomicInteger(0);
    
    @Scheduled(fixedDelay = 2000)
    public void fixedRateJob() {
        int jobId = counter.incrementAndGet();
        System.out.println("Job @ fixed delay " + new Date() + ", jobId: " + jobId);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Job " + jobId + " done");
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                SpringScheduleFixedDelayExample.class);
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.close();
        }
    }
}

The method execution takes around one second, the fixed delay is set to two seconds so between two invocations there is a delay of three seconds.

Output:

May 14, 2016 9:11:34 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:11:34 IST 2016]; root of context hierarchy
Job @ fixed delay Sat May 14 09:11:35 IST 2016, jobId: 1
Job 1 done
Job @ fixed delay Sat May 14 09:11:38 IST 2016, jobId: 2
Job 2 done
Job @ fixed delay Sat May 14 09:11:41 IST 2016, jobId: 3
Job 3 done
May 14, 2016 9:11:43 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:11:34 IST 2016]; root of context hierarchy

Spring scheduler with fixed rate

In this example we will use fixedRate attribute, it is used to define the fixed period between method invocations.

Spring Scheduler Fixed Rate

Spring Scheduler Fixed Rate

SpringScheduleFixedRateExample:

package com.javarticles.spring;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SpringScheduleFixedRateExample {

    private AtomicInteger counter = new AtomicInteger(0);
    
    @Scheduled(fixedRate = 2000)
    public void fixedRateJob() {
        int jobId = counter.incrementAndGet();
        System.out.println("Job @ fixed rate " + new Date() + ", jobId: " + jobId);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Job " + jobId + " done");
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                SpringScheduleFixedRateExample.class);
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.close();
        }
    }
}

The fixedRate is set to 2000 milliseconds so between two executions there is a delay of two seconds.

Output:

May 14, 2016 9:18:59 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:18:59 IST 2016]; root of context hierarchy
Job @ fixed rate Sat May 14 09:18:59 IST 2016, jobId: 1
Job 1 done
Job @ fixed rate Sat May 14 09:19:01 IST 2016, jobId: 2
Job 2 done
Job @ fixed rate Sat May 14 09:19:03 IST 2016, jobId: 3
Job 3 done
Job @ fixed rate Sat May 14 09:19:05 IST 2016, jobId: 4
Job 4 done
Job @ fixed rate Sat May 14 09:19:07 IST 2016, jobId: 5
Job 5 done

Spring Scheduler using cron expression

Cron expression gives us a greater control on when to schedule a task. We will now use a cron expression to schedule task. For example, cron expression /2 * * * * SAT,SUN,MON schedules a task to run every two seconds on Saturday, Sunday and Monday.

SpringScheduleCronExample:

package com.javarticles.spring;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SpringScheduleCronExample {
    private AtomicInteger counter = new AtomicInteger(0);

    @Scheduled(cron = "*/2 * * * * SAT,SUN,MON")
    public void cronJob() {
        int jobId = counter.incrementAndGet();
        System.out.println("Job @ cron " + new Date() + ", jobId: " + jobId);
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                SpringScheduleCronExample.class);
        try {
            Thread.sleep(12000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            context.close();
        }
    }
}

Output:

May 14, 2016 9:21:50 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:21:50 IST 2016]; root of context hierarchy
Job @ cron Sat May 14 09:21:52 IST 2016, jobId: 1
Job @ cron Sat May 14 09:21:54 IST 2016, jobId: 2
Job @ cron Sat May 14 09:21:56 IST 2016, jobId: 3
Job @ cron Sat May 14 09:21:58 IST 2016, jobId: 4
Job @ cron Sat May 14 09:22:00 IST 2016, jobId: 5
Job @ cron Sat May 14 09:22:02 IST 2016, jobId: 6
May 14, 2016 9:22:03 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicatio[email protected]: startup date [Sat May 14 09:21:50 IST 2016]; root of context hierarchy

Download the source code

This was an example about scheduling tasks using spring.

You can download the source code here: springScheduedAnnotationExample.zip

About Author

Ram's expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring. You can reach him at [email protected]

Comments are closed.