Spring Job Scheduling with @Scheduled & @EnableScheduling Annotations

In this post we will how to Schedule a Job in Spring using Spring @Scheduled and @EnableScheduling Annotations based Configuration. Let’s get going.


Following technologies being used:

  • Spring 4.0.6.RELEASE
  • Maven 3
  • JDK 1.6
  • Eclipse JUNO Service Release 2

Project directory structure:

Following will be the final project directory structure for this example:

Let’s now add the content mentioned in above structure explaining each in detail.

Step 1: Provide Spring dependencies in Maven pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.websystique.spring</groupId>
	<artifactId>SpringSchedulingAnnotationExample</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
	<name>SpringSchedulingAnnotationExample</name>

	<properties>
		<springframework.version>4.0.6.RELEASE</springframework.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${springframework.version}</version>
		</dependency>
	</dependencies>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.2</version>
					<configuration>
						<source>1.6</source>
						<target>1.6</target>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

</project>

Step 2: Create Spring Configuration Class

Spring configuration class are the ones annotated with @Configuration. These classes contains methods annotated with @Bean. These @Bean annotated methods generates beans managed by Spring container.

package com.websystique.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.websystique.spring.scheduling.MyBean;

@Configuration
@EnableScheduling
public class AppConfig {

	@Bean
	public MyBean bean() {
		return new MyBean();
	}

}

Notice @EnableScheduling. This annotation enables Spring’s scheduled task execution capability, similar to functionality found in Spring’s task namespace we saw in previous tutorial. Thanks to @EnableScheduling, all the bean methods annotated with @Scheduler will be registered for scheduling

Below is the Bean class itself:


package com.websystique.spring.scheduling;

import org.springframework.scheduling.annotation.Scheduled;

public class MyBean {

	@Scheduled(fixedRate=5000)
	public void printMessage() {
		System.out.println("I am called by Spring scheduler");
	}
}

Above @Scheduled annotated method will be called by Scheduler every 5 seconds. Note that the method which is annotated with @Scheduler must return void and must not have any parameters. Of course you can inject another bean in above bean to get some external functionality called in printMessage.

@Scheduled annotation have several attributes to specify different scheduling timelines. initialDelay attribute specifies the number of milliseconds to wait before the first execution of the method. fixedRate specifies the number of milliseconds between each method start , regardless of how long method takes to complete. fixedDelay specifies the number of milliseconds between completion of previous run, and start of next run.
Attribute cron provides more fine-grained control on task execution scheduling. For example, @Scheduled(cron=*/5 * * * * MON-FRI") configures this method to be executed every 5 seconds but only on weekdays.

Step 3: Create Main and Run it

package com.websystique.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.config.AppConfig;

public class AppMain {
	
	@SuppressWarnings({ "unused", "resource" })
	public static void main(String args[]){
		AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AppConfig.class);
	}

}

Note that we are not calling any explicit scheduling class or method here, just registering plain Configuration class. As we have annotated the configuration class with @EnableScheduling, the bean methods annotated with @Scheduler will automatically be registered for scheduling.

Run above program as Java Application, you will see following output

INFO: Bean 'org.springframework.scheduling.annotation.SchedulingConfiguration' of type [class org.springframework.scheduling.annotation.SchedulingConfiguration$$EnhancerBySpringCGLIB$$bcca717e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
I am called by Spring scheduler
I am called by Spring scheduler
I am called by Spring scheduler
I am called by Spring scheduler
I am called by Spring scheduler
.....

That’s it.

Now, as we discussed in previous post , in case you have tasks which can take long time to complete, and are frequent, you can optionally configure thread-pool with specified pool-size to handle each tasks in separate thread.

Below is the updated Configuration class with thread-pooling included

package com.websystique.spring.config;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import com.websystique.spring.scheduling.MyBean;

@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {

	@Bean
	public MyBean bean() {
		return new MyBean();
	}

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }

}

Above we have configured the scheduler with thread-pool of 10 threads.

Running main program with above changes provides same output, with additional thread-pool support.

Download Source Code


References