Enterprise Java

Spring and Quartz: Multi-Job Scheduling Service

Job Scheduling is so important requirement for the applications. Especially in large-scale projects, working with a lot of jobs can be a problem. Spring and Quartz have brought significant benefits for the solution of this problem. This article shows how to schedule multi jobs easily by using Spring and Quartz.

Used Technologies :

JDK 1.6.0_21
Spring 3.1.1
Quartz 1.8.5
Maven 3.0.2

STEP 1 : CREATE MAVEN PROJECT
A maven project is created as below. (It can be created by using Maven or IDE Plug-in)

STEP 2 : LIBRARIES
Spring dependencies are added to Maven’ s pom.xml.

<!-- Spring 3 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-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
</dependency>

STEP 3 : CREATE TASK CLASSES
A FirstTask Class is created.

package com.otv.task;
 
import org.apache.log4j.Logger;
 
/**
 * First Task
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class FirstTask {
 
    private static Logger log = Logger.getLogger(FirstTask.class);
 
    /**
     * Execute this task
     *
     */
    public void execute() {
        log.debug("FirstTask runs successfully...");
    }
}

A SecondTask Class is created.

package com.otv.task;
 
import org.apache.log4j.Logger;
 
/**
 * Second Task
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class SecondTask {
 
    private static Logger log = Logger.getLogger(SecondTask.class);
 
    /**
     * Execute this task
     *
     */
    public void execute() {
        log.debug("SecondTask runs successfully...");
    }
}

STEP 4 : CREATE ISchedulerService INTERFACE
ISchedulerService Interface is created.

package com.otv.service;
 
/**
 * Scheduler Service Interface
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public interface ISchedulerService {
 
    /**
     * Execute First Task
     *
     * @param
     * @throws
     * @return
     */
    public void executeFirstTask();
 
    /**
     * Execute Second Task
     *
     * @param
     * @throws
     * @return
     */
    public void executeSecondTask();
}

STEP 5 : CREATE SchedulerService CLASS
SchedulerService Class is created by implementing ISchedulerService Interface. This service schedules tasks.

package com.otv.service;
 
import com.otv.task.FirstTask;
import com.otv.task.SecondTask;
 
/**
 * Scheduler Service Implementation
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class SchedulerService implements ISchedulerService {
 
    private FirstTask  firstTask;
    private SecondTask secondTask;
 
    /**
     * Execute First Task
     *
     */
    public void executeFirstTask() {
        getFirstTask().execute();
    }
 
    /**
     * Execute Second Task
     *
     */
    public void executeSecondTask() {
        getSecondTask().execute();
    }
 
    /**
     * Get First Task
     *
     * @return FirstTask
     */
    public FirstTask getFirstTask() {
        return firstTask;
    }
 
    /**
     * Set First Task
     *
     * @param  firstTask First Task
     */
    public void setFirstTask(FirstTask firstTask) {
        this.firstTask = firstTask;
    }
 
    /**
     * Get Second Task
     *
     * @return SecondTask
     */
    public SecondTask getSecondTask() {
        return secondTask;
    }
 
    /**
     * Set Second Task
     *
     * @param  secondTask Second Task
     */
    public void setSecondTask(SecondTask secondTask) {
        this.secondTask = secondTask;
    }
}

STEP 6 : CREATE Application CLASS
Application Class is created. This class runs the application.

package com.otv.starter;
 
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * Application Starter Class
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class Application {
 
    /**
     * Main method of the Application
     *
     */
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

STEP 7 : DEFINE Job Detail CONFIGURATIONS
Job Details can be defined via two ways in Spring. By using MethodInvokingJobDetailFactoryBean or by extending QuartzJobBean. In this example, MethodInvokingJobDetailFactoryBean method has been used. targetObject and targetMethod properties are given to MethodInvokingJobDetailFactoryBean.

<!-- Job Details-->
<bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="SchedulerService" />
    <property name="targetMethod" value="executeFirstTask" />
</bean>
 
<bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="SchedulerService" />
    <property name="targetMethod" value="executeSecondTask" />
</bean>

STEP 8 : DEFINE Trigger CONFIGURATIONS
Triggers can also be defined via two ways in Spring. By defining SimpleTriggerBean or CronTriggerBean . When SimpleTriggerBean is used, jobDetail, repeatInterval and startDelay properties are defined. When CronTriggerBean is used, jobDetail and cronExpression properties are defined. In this example, repeat interval of first task has been set 5 secs and repeat interval of second task has been set 12 secs .

<!-- Simple Trigger -->
<bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="FirstTaskJobDetail" />
    <property name="repeatInterval" value="5000" />
    <property name="startDelay" value="1000" />
</bean>
 
<!-- <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="repeatInterval" value="12000" />
        <property name="startDelay" value="1000" />
    </bean> -->   
 
<!-- Cron Trigger -->
<bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="SecondTaskJobDetail" />
    <property name="cronExpression" value="0/12 * * * * ?" />
</bean>

STEP 9 : DEFINE SchedulerFactoryBean CONFIGURATION
Finally, Job Details and Triggers are configured by creating SchedulerFactoryBean.

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
       <list>
          <ref bean="FirstTaskJobDetail" />
          <ref bean="SecondTaskJobDetail" />
       </list>
    </property>
    <property name="triggers">
       <list>
          <ref bean="FirstSimpleTrigger" />
          <ref bean="SecondSimpleTrigger" />
       </list>
    </property>
</bean>

STEP 10 : CREATE applicationContext.xml
All applicationContext.xml content is shown as below.

<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">
 
    <!-- Beans Declaration -->
    <bean id="FirstTask" class="com.otv.task.FirstTask"></bean>
    <bean id="SecondTask" class="com.otv.task.SecondTask"></bean>
 
    <bean id="SchedulerService" class="com.otv.service.SchedulerService">
        <property name="firstTask" ref="FirstTask" />
        <property name="secondTask" ref="SecondTask" />
    </bean>
 
    <!-- Job Details-->
    <bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="SchedulerService" />
        <property name="targetMethod" value="executeFirstTask" />
    </bean>
 
    <bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="SchedulerService" />
        <property name="targetMethod" value="executeSecondTask" />
    </bean>
 
    <!-- Simple Trigger -->
    <bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="FirstTaskJobDetail" />
        <property name="repeatInterval" value="5000" />
        <property name="startDelay" value="1000" />
    </bean>
<!--
    <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="repeatInterval" value="12000" />
        <property name="startDelay" value="1000" />
    </bean>
-->
    <!-- Cron Trigger -->
    <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="cronExpression" value="0/12 * * * * ?" />
    </bean>
 
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobDetails">
           <list>
              <ref bean="FirstTaskJobDetail" />
              <ref bean="SecondTaskJobDetail" />
           </list>
        </property>
        <property name="triggers">
           <list>
              <ref bean="FirstSimpleTrigger" />
              <ref bean="SecondSimpleTrigger" />
           </list>
        </property>
    </bean>
 
</beans>

STEP 11 : RUN PROJECT
After Application Class is started, below output logs will be shown :

25.02.2012 00:17:18 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:23 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:24 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:28 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:33 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:36 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:38 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:43 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:48 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:48 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:53 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:58 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:18:00 DEBUG (SecondTask.java:22) - SecondTask runs successfully...

STEP 12 : DOWNLOAD

OTV_SpringQuartz_MultiJobScheduling

Reference: Multi-Job Scheduling Service by using Spring and Quartz from our JCG partner Eren Avsarogullari at the Online Technology Vision blog.

Subscribe
Notify of
guest

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

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Shahzada Hatim
12 years ago

it’s all great but I don’t see the point of all the comments which say the exact same thing as code.

Hidayath
Hidayath
10 years ago

Unable to download the file in step 12

Mirza Gaush
Mirza Gaush
10 years ago

Thank you much for a good tutorial. It gives a good insight about Spring+Quartz implementation but it has got few redundant code,
47
48
49
50
51
52

As the defined jobs are already referenced in JobTriggers and hence it does not require to be defined in SchedulerFactory Configuration

Renzo
Renzo
10 years ago

I’m a rookie with spring and quartz too , I’ve had a lot of problems trying to do a simple example of this. Thanks a lot.

Back to top button