Beans

Spring 3 Scheduler Example – JDK Timer and Quartz Showcase

Spring Framework provides abstractions for execution and scheduling of tasks, supporting thread pools or delegation to CommonJ within an application server environment. Spring also features integration classes for supporting scheduling with the JDK Timer and the Quartz Scheduler, provided by the Quartz scheduling library. Both schedulers are set up using a FactoryBean with optional references to Timer or org.quartz.Trigger instances, respectively. Furthermore, a convenience class for both the Timer and the Quartz Scheduler is available that allows us to invoke a method of an existing target object.

In this tutorial we shall show you how to implement a JDK Timer Scheduler example in Spring and then we will enrich the example, using the Quartz Scheduler.

Our preferred development environment is Eclipse. We are using Eclipse Juno (4.2) version, along with Maven Integration plugin version 3.1.0. You can download Eclipse from here and Maven Plugin for Eclipse from here. The installation of Maven plugin for Eclipse is out of the scope of this tutorial and will not be discussed. We are also using Spring version 3.2.3 and the JDK 7_u_21.

Let’s begin.

1. Create a new Maven project

Go to File -> Project ->Maven -> Maven Project.

New-Maven-Project

In the “Select project name and location” page of the wizard, make sure that “Create a simple project (skip archetype selection)” option is checked, hit “Next” to continue with default values.

Maven-Project-Name-Location

In the “Enter an artifact id” page of the wizard, you can define the name and main package of your project. We will set the “Group Id” variable to "com.javacodegeeks.snippets.enterprise" and the “Artifact Id” variable to "springexample". The aforementioned selections compose the main project package as "com.javacodegeeks.snippets.enterprise.springexample" and the project name as "springexample". Hit “Finish” to exit the wizard and to create your project.

Configure-Maven-Project

The Maven project structure is shown below:

Maven-project-structure

    It consists of the following folders:

  • /src/main/java folder, that contains source files for the dynamic content of the application,
  • /src/test/java folder contains all source files for unit tests,
  • /src/main/resources folder contains configurations files,
  • /target folder contains the compiled and packaged deliverables,
  • the pom.xml is the project object model (POM) file. The single file that contains all project related configuration.

2. Add Spring 3.2.3 dependency

  • Locate the “Properties” section at the “Overview” page of the POM editor and perform the following changes:
    Create a new property with name org.springframework.version and value 3.2.3.RELEASE.
  • Navigate to the “Dependencies” page of the POM editor and create the following dependencies (you should fill the “GroupId”, “Artifact Id” and “Version” fields of the “Dependency Details” section at that page):
    Group Id : org.springframework Artifact Id : spring-web Version : ${org.springframework.version}

Alternatively, you can add the Spring dependencies in Maven’s pom.xml file, by directly editing it at the “Pom.xml” page of the POM editor, as shown below:
 
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.javacodegeeks.snippets.enterprise</groupId>
	<artifactId>springexample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>

	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>
</project>

As you can see Maven manages library dependencies declaratively. A local repository is created (by default under {user_home}/.m2 folder) and all required libraries are downloaded and placed there from public repositories. Furthermore intra – library dependencies are automatically resolved and manipulated.

3. Add the Quartz dependency

Add the Quartz dependency in pom.xml file.

<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.javacodegeeks.snippets.enterprise</groupId>
	<artifactId>springexample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>3.1.2.RELEASE</version>
		</dependency>

		<!-- Quartz framework -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>1.8.6</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>
</project>α

4. JDK Timer Scheduler in Spring

4.1 Create a simple task

MyTask.java class is a simple task that will be scheduled to run.

MyTask.java

package com.javacodegeeks.snippets.enterprise;

public class MyTask {
	public void sayHello() {
		System.out.println("Hello !!! ");
	}
}

4.2 Configure applicationContext.xml with the Scheduler and the Timer

Spring replaces the JDK TimerTask, that is a task that can be scheduled for one-time or repeated execution by a Timer, with its own implementation, that is the org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean. It also provides an implementation of JDK Timer, that is a facility for threads to schedule tasks for future execution in a background thread, with its own implementation, that is the org.springframework.scheduling.timer.ScheduledTimerTask.
In addition, a TimerFactoryBean is defined, so that the scheduled task begins execution. It is a FactoryBean that sets up a Timer and exposes it for bean reference. It allows for registration of the ScheduledTimerTask, automatically starting the Timer on initialization and cancelling it on destruction of the context.

All we need to schedule our task for execution is to define all classes mentioned above in applicationContext.xml. We define the MyTask.java class in myTask bean. We also define the schedulerTask bean, that is the bean of the TimerTask. It has two properties to configure. The targetObject property’s value is a reference to the bean of the task we have implemented, that is myTask. The targetMethod property’s value is the name of the task’s method that is scheduled to run.

The timerTask bean is the bean of the Timer. It holds a timerTask property, where we can set the reference to the timerTask bean configured above. Here we can configure the delay before starting the task for the first time, in milliseconds, using the delay property. We can also set the period between repeated task executions, in milliseconds, using the period property. We configure the timer to run every 5 seconds, with delay of 1 second.

The TimerFactoryBean is also defined in applicationContext.xml. We can register a list of ScheduledTimerTask objects with the Timer that this FactoryBean creates, in the scheduledTimerTask property. So here, we register the timerTask.

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

  
 <bean id="myTask" class="com.javacodegeeks.snippets.enterprise.MyTask" />
 
 <bean id="schedulerTask" 
  class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
	<property name="targetObject" ref="myTask" />
	<property name="targetMethod" value="sayHello" />
</bean>

<bean id="timerTask"
	class="org.springframework.scheduling.timer.ScheduledTimerTask">
	<property name="timerTask" ref="schedulerTask" />
	<property name="delay" value="1000" />
	<property name="period" value="5000" />
</bean>

<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
	<property name="scheduledTimerTasks">
		<list>
			<ref local="timerTask" />
		</list>
	</property>
</bean>
</beans>

5 Quartz Scheduler

5.1 Quartz Scheduler Job

In order to enrich the example with the Quartz Scheduler we first have to set a Quartz scheduler job. This can be done in two ways. The first way is to define the scheduler job as a Spring bean in applicationContext.xml. It can be a bean of org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
class, with two properties to configure, the targetObject and the targetMethod, just like we did in the previous step. But let’s try a more complex scheduler. We can implement our own scheduler, just by creating a class that extends the org.springframework.scheduling.quartz.QuartzJobBean. The MyTask.java class can be passed to the scheduler job via a setter method. Then, the task’s method is invoked in the executeInternal(JobExecutionContext context) method that the scheduler job inherits from the QuartzJobBean.

QuartzJob.java

package com.javacodegeeks.snippets.enterprise.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.javacodegeeks.snippets.enterprise.MyTask;

public class QuartzJob extends QuartzJobBean {
	
	private MyTask myTask;

	public void setMyTask(MyTask myTask) {
		this.myTask = myTask;
	}

	protected void executeInternal(JobExecutionContext context)
		throws JobExecutionException {
		myTask.sayHello(); 
	}
}

5.2 Quartz Trigger

Now we have to define the Quartz Trigger that will run the scheduler job. Quartz provides two classes to implement the triggering part. In the org.springframework.scheduling.quartz.SimpleTriggerBean we can set the startTime, endTime and intervals to run the job, whereas the org.springframework.scheduling.quartz.CronTriggerBean supports the UNIX cron expression to specify the time that the job will run. Both trigger classes are defined as Spring beans, and both provide a jobDetail property where the scheduler job is a reference.

One more step to configure is to create a SchedulerFactoryBean, that can integrate both the scheduler job and the trigger. So both beans are included in the SchedulerFactoryBean bean definition.

In applicationContext.xml we define all beans for the scheduler job, the trigger and the SchedulerFactoryBean.

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

  
 <bean id="myTask" class="com.javacodegeeks.snippets.enterprise.MyTask" />

<!-- quartz -->
	<bean name="quartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">
		<property name="jobClass" value="com.javacodegeeks.snippets.enterprise.quartz.QuartzJob" />
		<property name="jobDataAsMap">
		  <map>
			<entry key="myTask" value-ref="myTask" />
		  </map>
		</property>
	</bean>
	
	<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> 
		<property name="jobDetail" ref="quartzJob" />
		<property name="repeatInterval" value="5000" />
		<property name="startDelay" value="1000" />
	</bean>
 
	<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
 		<property name="jobDetail" ref="quartzJob" />
		<property name="cronExpression" value="0/5 * * * * ?" /> 
	</bean>
 
	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobDetails">
			<list>
				<ref bean="quartzJob" />
			</list>
		</property> 
		<property name="triggers">
			<list>
				<ref bean="cronTrigger" />
			</list>
		</property>
	</bean>
</beans>

Note that both implementations for the Trigger are added, but only one is used in the SchedulerFactoryBean bean definition. cronTrigger is the bean of the org.springframework.scheduling.quartz.CronTriggerBean implementation, whereas the simpleTrigger is the bean of the org.springframework.scheduling.quartz.SimpleTriggerBean implementation. In SchedulerFactoryBean bean’s property triggers a reference to the cronTrigger is set, whereas in its jobDetails property the scheduler job is set.

Another thing to notice is the quartzJob bean definition. Here the QuartzJob class is defined as a property of the org.springframework.scheduling.quartz.JobDetailBean class. The class has a jobDataAsMap property, where the task is registered.

6. Run the application

In App.java class, we load applicationContext.xml file and cause the thread running the application to sleep for 30 seconds before closing the context. For as long as the context is open the task runs as scheduled above. The sayHello() method is invoked every 5 seconds, in both cases.

App.java

package com.javacodegeeks.snippets.enterprise;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

	public static void main(String[] args) throws InterruptedException {
		ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Thread.sleep(30000);
		context.close();
	}

}

 
This was an example of a Spring 3 Scheduler implementation of the JDK Timer and Quartz.
Download the Eclipse project of this tutorial : SpringSchedulerQuartzExample.zip

Theodora Fragkouli

Theodora has graduated from Computer Engineering and Informatics Department in the University of Patras. She also holds a Master degree in Economics from the National and Technical University of Athens. During her studies she has been involved with a large number of projects ranging from programming and software engineering to telecommunications, hardware design and analysis. She works as a junior Software Engineer in the telecommunications sector where she is mainly involved with projects based on Java and Big Data technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button