Spring 3 + Quartz 1.8.6 scheduler example

Updated on 25 July 2012 – Upgrade article to use Spring 3 and Quartz 1.8.6 (it was Spring 2.5.6 and Quartz 1.6)

In this tutorial, we will show you how to integrate Spring with Quartz scheduler framework. Spring comes with many handy classes to support Quartz, and decouple your class to Quartz APIs.

Tools Used :

  1. Spring 3.1.2.RELEASE
  2. Quartz 1.8.6
  3. Eclipse 4.2
  4. Maven 3
Why NOT Quartz 2?
Currently, Spring 3 is still NOT support Quartz 2 APIs, see this SPR-8581 bug report. Will update this article again once bug fixed is released.

1. Project Dependency

You need following dependencies to integrate Spring 3 and Quartz 1.8.6

File : pom.xml


...
<dependencies>

	<!-- Spring 3 dependencies -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>3.1.2.RELEASE</version>
	</dependency>

	<!-- QuartzJobBean in spring-context-support.jar -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context-support</artifactId>
		<version>3.1.2.RELEASE</version>
	</dependency>

	<!-- Spring + Quartz need transaction -->
	<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>
...

2. Scheduler Task

Create a normal Java class, this is the class you want to schedule in Quartz.

File : RunMeTask.java


package com.mkyong.common;

public class RunMeTask {
	public void printMe() {
		System.out.println("Spring 3 + Quartz 1.8.6 ~");
	}
}

3. Declare Quartz Scheduler Job

With Spring, you can declare Quartz job in two ways :

3.1 MethodInvokingJobDetailFactoryBean
This is the simplest and straightforward method, suitable for simple scheduler.


<bean id="runMeJob" 
 	class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		
	<property name="targetObject" ref="runMeTask" />
	<property name="targetMethod" value="printMe" />
		
</bean>

3.2 JobDetailBean
The QuartzJobBean is more flexible and suitable for complex scheduler. You need to create a class extends the Spring’s QuartzJobBean, and define the method you want to schedule in executeInternal() method, and pass the scheduler task (RunMeTask) via setter method.

File : RunMeJob.java


package com.mkyong.common;

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

public class RunMeJob extends QuartzJobBean {
	private RunMeTask runMeTask;

	public void setRunMeTask(RunMeTask runMeTask) {
		this.runMeTask = runMeTask;
	}

	protected void executeInternal(JobExecutionContext context)
		throws JobExecutionException {

		runMeTask.printMe();

	}
}

Configure the target class via jobClass and method to run via jobDataAsMap.


<bean name="runMeJob" class="org.springframework.scheduling.quartz.JobDetailBean">
	
	<property name="jobClass" value="com.mkyong.common.RunMeJob" />
		
	<property name="jobDataAsMap">
		<map>
			<entry key="runMeTask" value-ref="runMeTask" />
		</map>
	</property>
		
</bean>

4. Trigger

Configure Quartz trigger to define when will run your scheduler job. Two type of triggers are supported :

4.1 SimpleTrigger
It allows to set the start time, end time, repeat interval to run your job.


        <!-- Simple Trigger, run every 5 seconds -->
	<bean id="simpleTrigger" 
                class="org.springframework.scheduling.quartz.SimpleTriggerBean">
		
		<property name="jobDetail" ref="runMeJob" />
		<property name="repeatInterval" value="5000" />
		<property name="startDelay" value="1000" />
		
	</bean>

4.2 CronTrigger
It allows Unix cron expression to specify the dates and times to run your job.


	<!-- Cron Trigger, run every 5 seconds -->
	<bean id="cronTrigger"
		class="org.springframework.scheduling.quartz.CronTriggerBean">
	
		<property name="jobDetail" ref="runMeJob" />
		<property name="cronExpression" value="0/5 * * * * ?" />
	
	</bean>
Note
The Unix cron expression is highly flexible and powerful, read more in following websites :

  1. http://en.wikipedia.org/wiki/CRON_expression
  2. http://www.quartz-scheduler.org/docs/examples/Example3.html

5. Scheduler Factory

Create a Scheduler factory bean to integrate both job detail and trigger together.


   <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="jobDetails">
	   <list>
	      <ref bean="runMeJob" />
	   </list>
	</property>
		
	<property name="triggers">
	    <list>
		<ref bean="simpleTrigger" />
	    </list>
	</property>
   </bean>

6. Spring Bean Configuration File

Complete Spring’s bean configuration file.

File : Spring-Quartz.xml


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<bean id="runMeTask" class="com.mkyong.common.RunMeTask" />

	<!-- Spring Quartz -->
	<bean name="runMeJob" class="org.springframework.scheduling.quartz.JobDetailBean">

		<property name="jobClass" value="com.mkyong.common.RunMeJob" />

		<property name="jobDataAsMap">
		  <map>
			<entry key="runMeTask" value-ref="runMeTask" />
		  </map>
		</property>

	</bean>

	<!-- 
	<bean id="runMeJob" 
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 
		<property name="targetObject" ref="runMeTask" /> 
		<property name="targetMethod" value="printMe" /> 
	</bean> 
	-->

	<!-- Simple Trigger, run every 5 seconds -->
	<bean id="simpleTrigger" 
                class="org.springframework.scheduling.quartz.SimpleTriggerBean">

		<property name="jobDetail" ref="runMeJob" />
		<property name="repeatInterval" value="5000" />
		<property name="startDelay" value="1000" />

	</bean>

	<!-- Cron Trigger, run every 5 seconds -->
	<bean id="cronTrigger" 
                class="org.springframework.scheduling.quartz.CronTriggerBean">

		<property name="jobDetail" ref="runMeJob" />
		<property name="cronExpression" value="0/5 * * * * ?" />

	</bean>

	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobDetails">
			<list>
				<ref bean="runMeJob" />
			</list>
		</property>

		<property name="triggers">
			<list>
				<ref bean="simpleTrigger" />
			</list>
		</property>
	</bean>

</beans>

7. Demo

Run it ~


package com.mkyong.common;
 
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class App 
{
    public static void main( String[] args ) throws Exception
    {
    	new ClassPathXmlApplicationContext("Spring-Quartz.xml");
    }
}

Output to console.


Jul 25, 2012 3:23:09 PM org.springframework.scheduling.quartz.SchedulerFactoryBean startScheduler
INFO: Starting Quartz Scheduler now
Spring 3 + Quartz 1.8.6 ~ //run every 5 seconds
Spring 3 + Quartz 1.8.6 ~

Download Source Code

Download it – Spring3-Quartz-Example.zip (25 KB)

References

  1. Using Quartz Scheduler with Spring
  2. Quartz Official Website
  3. Struts 2 + Spring 3 + Quartz 1.8 example

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
86 Comment threads
30 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
92 Comment authors
luisvasvTFKNehajackHari Krishna Recent comment authors
newest oldest most voted
Neha
Guest
Neha

How we can use Quartz with database if I want to query over database in every 10 min ? Could you please developed a code for that ?

Hari Krishna
Guest
Hari Krishna

hi how to dynamically change cron expression during runtime. Like the cron expression will be changed in database;so according to change the cron expression should change

jack
Guest
jack

I have a similar requirement?? did u get any solution

luisvasv
Guest
luisvasv

Works for me , thanks!!

TFK
Guest
TFK

Where does the XML reside within the project ? I’m speaking of the XML shown in section 3.1, 4.1, 5,

Lokesh Gowda
Guest
Lokesh Gowda

Hi Mkyong

i am using the quartz schduler in our application where in the example we are specifying the applicationxml context from the Spring-Quartz.xml is it mandatory to have that xml for every scheduler or we can embed the same with existing xml will it work

Green Lei
Guest
Green Lei

Hi mkyong,

I want to test JobDetailBean as runMeJob, how to do it, please?

anonymous
Guest
anonymous

Great help in understanding basics.

TK2020
Guest
TK2020

Hi, I am Setting requestRecovery(true) to recover the job that was running during server hard shut-down. But it is not working with quartz 1.8.6. I tried in different forms but failed. later I just tested with my old quartz jar 1.6.2 and it works. Below is my sample code. JobDetail myJob = new JobDetail(); myJob.setName(“TestJob”); myJob.setGroup(“JobGroup”); myJob.setJobClass(Alarm.class); myJob.setRequestsRecovery(true); SimpleTrigger myTrigger = new SimpleTrigger(); myTrigger.setName(“TestTrigger”); myTrigger.setGroup(“TriggerGroup”); myTrigger.setStartTime(1234567890); myTrigger.setRepeatCount(0); myTrigger.setMisfireInstruction(MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_ COUNT); mySched.scheduleJob(myJob, myTrigger); Is this an bug in quartz 1.8.6 or do I miss anything special to configure which was actually not required in quartz 1.6.2. If so, can someone put a… Read more »

Diego Plentz
Guest
Diego Plentz

Hi! If you schedule a job this way, it will have dependency injection as well?

Robin Mathur
Guest
Robin Mathur

Please update the post as SPR-8581 bug report has been resolved.

ruen
Guest
ruen

Thank you for this :) this guide allowed me to create a simple scheduler as a study

Majid Lotfi
Guest
Majid Lotfi

Hi,

This line :

org.springframework.scheduling.quartz.QuartzJobBean;

has an error :

The import org.springframework.scheduling.quartz cannot be

resolved.

Can you please help me ?
Thanks

raju
Guest
raju

Hi mkyong,

I used Quartz scheduler in my Spring-Hibernate App based on You Nice Explanation.It is working fine,But The Threads Started for Quartz Scheduler are not destroying…and my server gives Errors(Memory Leaks) like….

org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/app] appears to have started a thread named [schedularbeanfactoryobj_Worker-1] but has failed to stop it. This is very likely to create a memory leak.
….
….

I have Tried With Many solutions to shutdown those threads but could not fixed.Can anybody Help To fix this.(i am using spring3.2.2 and quartz1.8.6)and also tried with quartz2.2.

Thanks
raju.

Deepa
Guest
Deepa

Hi Raju – Could you please guide how we can developed application with hibernate + spring + quartz? Could you please provide your sample code?

Diana
Guest
Diana

Hi, is it possible to make spring not to trigger the cronjob is the previous trigged job is still running?

Humberto Souza
Guest
Humberto Souza

Hi Diana,

The jobs are synchonous by default. So, even if you trigger the task that is already executing, it will not fire the second.
If you want fire the same task at same time, should use assync methods.

raju
Guest
raju

Hi,

From Spring Doc…

“By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with each other. If
you specify two triggers for the same JobDetail, it might be possible that before the first job has
finished, the second one will start. If JobDetail classes implement the Stateful interface, this won’t
happen. The second job will not start before the first one has finished. To make jobs resulting from the
MethodInvokingJobDetailFactoryBean non-concurrent, set the concurrent flag to false.

Diana
Guest
Diana

I finally created a class to be a singleton. It’s an static property of the task (not the job), with an internal flag (private Boolean running = false;) with a method to change status (public void changeStatus() {running = !running;}), and a method to know its value (isRunning()). So when the task is running, it checks if there is another thread running: if (!mySingleton.isRunning()) { mySingleton.changeStatus(); //whatever the task has to do here mySingleton.changeStatus(); } else { logger.warn(“Task won’t be executed, there is another instance of this job running.”); } Something like that, I don’t have my code here. But… Read more »

Prasad
Guest
Prasad

Sir , I am using Spring 3.1.1 and quartz 1.8.5 like above example .but i am getting exception like below .anyone help me ! Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘job’ defined in class path resource [META-INF/applicationContext.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property ‘jobclass’ of bean class [org.springframework.scheduling.quartz.JobDetailBean]: Bean property ‘jobclass’ is not writable or has an invalid setter method. Did you mean ‘jobClass’? at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83) at com.rcent.samples.SchedulerApp.main(SchedulerApp.java:11)… Read more »

Nish
Guest
Nish

Hi..

Thanks..it works gud but i have spring application, I am importing the quarts-job.xml in application-servlet.xml. There are no error’s and during the server startup it shows” Starting Quartz Scheduler now” but the task is not fired Any idea what might be the issue.

Thanks,
Nishith

raju
Guest
raju

can you post your Quartz Configurations..

Brownie
Guest
Brownie

Did you solve this issue, I am having the same issue

Marcelo Lior
Guest
Marcelo Lior

Great contribution! Straight to the point. Thanks a lot

Suraj
Guest
Suraj

When I execute the App.java, I am not able to see any output on the console.

The Eclipse console only shows:
Sep 18, 2013 12:53:32 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1113708: startup date [Wed Sep 18 12:53:32 IST 2013]; root of context hierarchy
Sep 18, 2013 12:53:32 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-quartz.xml]
Sep 18, 2013 12:53:32 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1a33d48: defining beans [runMeTask,runMeJob,simpleTrigger]; root of factory hierarchy

Can someone help me to get this resolved?
I am using spring 3.1.2 and quartz 1.8.6

Thanking in advance!!

Diana
Guest
Diana

Thank you very much, these is better than what I used to schedule a job. In fact, it solved me a problem. Thank you very much!

mkyong
Guest
mkyong

Its ok

Catalin
Guest
Catalin

How can i do a Unit test for this scheduler to see if it print the message in the write time interval?

Suman
Guest
Suman

Very good article. its easy to understand

Bilal
Guest
Bilal

It is very simple and concise article to understand the basic concepts. Thanks

Darshan
Guest
Darshan

Could not autowire field: org.processor.repository.NotificationRepository org.processor.services.ProcessorService.notificationRepository; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.scheduling.quartz.JobDetailBean] for bean with name ‘runMeJob’ defined in ServletContext resource [/WEB-INF/quartz-job.xml]: problem with class file or dependent class; nested exception is java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.JobDetailBean has interface org.quartz.JobDetail as super class

when i try to integrate this project in my maven project i am recieving above error?
please help

Alimotte
Guest
Alimotte

Hi,
In my application youre tutorial give me this error:

java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal

The solution to resolve it was:

xml-apis
xml-apis
1.4.01

Thank’s for all your help! Everyday when I have a problem, you have the solution! ;)

Alimotte
Guest
Alimotte

It’s a fail, sorry! :D
Add in pom.xml:

xml-apis
xml-apis
1.4.01

Alimotte
Guest
Alimotte

Ok balise is escaped…
so:
dependency
groupId org.quartz-scheduler /groupId
artifactId quartz /artifactId
version 1.8.6 /version
/dependency

Sorry for spam :)

Dmitry
Guest
Dmitry

Your example works only if you use

If you like to work this application with JobDetailsBean you should fixed it:

public class RunMeJob extends JobDetailBean { // it is empty.
}
and RunMeTask must implement Job interface
public class RunMeTask implements Job {
public void execute(JobExecutionContext jec) throws JobExecutionException {
System.out.println(“Quartz test job executed.”);
}
}

Swetha
Guest
Swetha

Thanks Mkyong, you always explain the concepts simple and easy so that novice person also can understand. your articles are very helpful to me. Thank you so much.

name
Guest
name

It seems that issue of https://jira.springsource.org/browse/SPR-8581 has labeled as won’t fix so you can update your article.

Ayodeji Babaniyi
Guest
Ayodeji Babaniyi

There is a small addition needed for the downloaded version to fully build and work out of the box: Simply add this dependency to the pom.xml

org.junit
com.springsource.junit
3.8.2
test
jar

That way it would compile and run out of the box.

Findeclinic
Guest
Findeclinic

The bug SPR-8581, looks resolved. Could you try updating? I failed :(

Guillermo
Guest
Guillermo

Simple, well explained and functional. I have lost the count of the times I ended up in your blog looking for answers.

Thanks!

rybek
Guest
rybek

I fully agree with Gullermo.

Thanks! and keep the posts comming ;)

Hector
Guest
Hector

A Co-worker and I just said “We always land on this dude’s blog!” Thank you Mkyong

James
Guest
James

Nice example. Helped a lot. Thanks.