Main Tutorials

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 Author

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

Comments

Subscribe
Notify of
112 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Neha
7 years ago

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
7 years ago

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
7 years ago
Reply to  Hari Krishna

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

akshay
3 years ago

Jobs added with no trigger must be durable.. I am facing this issue.. can you pls help

luisvasv
6 years ago

Works for me , thanks!!

TFK
6 years ago

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

Lokesh Gowda
8 years ago

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
8 years ago

Hi mkyong,

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

anonymous
9 years ago

Great help in understanding basics.

TK2020
9 years ago

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 sample code to show how to achieve it.

Diego Plentz
9 years ago
Reply to  TK2020

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

Robin Mathur
9 years ago

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

ruen
10 years ago

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

Majid Lotfi
10 years ago

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
10 years ago

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
8 years ago
Reply to  raju

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

Diana
10 years ago

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

Diana
10 years ago
Reply to  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 from everything I tried, it was the only thing that actually avoid running the same task twice at the same time. (Of course, I haven’t tried all the possibilities, but that solution worked for me).

raju
10 years ago
Reply to  Diana

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.

Humberto Souza
10 years ago
Reply to  Diana

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.

Prasad
10 years ago

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)
Caused by: 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.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1064)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:924)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
… 13 more

Nish
10 years ago

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

Brownie
9 years ago
Reply to  Nish

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

raju
10 years ago
Reply to  Nish

can you post your Quartz Configurations..

Marcelo Lior
10 years ago

Great contribution! Straight to the point. Thanks a lot

Suraj
10 years ago

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
10 years ago

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
10 years ago
Reply to  Diana

Its ok

Catalin
10 years ago

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

Suman
10 years ago

Very good article. its easy to understand

Bilal
10 years ago

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

Darshan
10 years ago

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
10 years ago

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
10 years ago
Reply to  Alimotte

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

xml-apis
xml-apis
1.4.01

Alimotte
10 years ago
Reply to  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
10 years ago

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
10 years ago

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
10 years ago

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
10 years ago

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
10 years ago

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

Guillermo
10 years ago

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

Thanks!

rybek
10 years ago
Reply to  Guillermo

I fully agree with Gullermo.

Thanks! and keep the posts comming 😉

Hector
10 years ago
Reply to  rybek

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