Friday, 23 September 2016

1. Spring Quartz Scheduler - Using MethodInvokingJobDetailFactoryBean

In this tutorial, we will see how to schedule jobs using "Quartz Scheduler" with Spring. There are few utility classes Spring provides to configure jobs and trigger execution based on schedule.

Following are tools/library versions used:
  • Spring 4.3.3.RELEASE
  • Quartz 2.2.3
  • Maven 3
  • JDK 1.8
  • Eclipse Mars
Create maven based project and add below dependencies in pom.xml for Spring and Quartz.
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<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>in.blogspot.ashish4java</groupId>
  <artifactId>SimpleSpringQuartzScheduler</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>SimpleSpringQuartzScheduler</name>
  <description>Simple Spring Quartz Scheduler tutorial with method invocation and simple trigger</description>
      <properties>
        <springframework.version>4.3.3.RELEASE</springframework.version>
        <quartz.version>2.2.3</quartz.version>
    </properties> 
    <dependencies>    
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>${quartz.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>
    </dependencies>
</project>


There are two ways to configure jobs using Spring. We will look into 'MethodInvokingJobDetailFactoryBean' which is used to invoke method. This is just to schedule invocation of single method call.

Job class:
This class contains method which needs to be invoked as per schedule.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
package in.blogspot.ashish4java.simplespringquartzexample.scheduler;

public class MyJob {

 
 public void task() {
  System.out.println("Task execution in progress...");
 }

}

Spring Configuration:
Now, configure MyJob bean in Spring configuration file along with "MethodInvokingJobDetailFactoryBean" bean which takes properties of 'targetObject' and 'targetMethod'
1
2
3
4
5
6
7
8
<bean id="myJob"
  class="in.blogspot.ashish4java.simplespringquartzexample.scheduler.MyJob" />

 <bean id="methodInvocationConfig"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <property name="targetObject" ref="myJob" />
  <property name="targetMethod" value="task"></property>
 </bean>

Job Trigger:
There are two types of triggers 
1. Simple Trigger which can be configured to invoke for certain number of times with delay in between each execution.
2. Cron Trigger which takes parameter like Cron job and can be scheduled with more control over schedule.

We will configure using Simple Trigger:
1
2
3
4
5
6
 <bean id="simpleTrigger"
  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
  <property name="jobDetail" ref="methodInvocationConfig" />
  <property name="repeatInterval" value="1000" />
  <property name="repeatCount" value="3" />
 </bean>


Now, let's put together this job and trigger:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="triggers">
   <list>
    <ref bean="simpleTrigger" />
   </list>
  </property>
  <property name="jobDetails">
   <list>
    <ref bean="methodInvocationConfig" />
   </list>
  </property>
 </bean>


Complete Spring configuration file:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<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-4.3.xsd">


 <bean id="myJob"
  class="in.blogspot.ashish4java.simplespringquartzexample.scheduler.MyJob" />

 <bean id="methodInvocationConfig"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <property name="targetObject" ref="myJob" />
  <property name="targetMethod" value="task"></property>
 </bean>

 <bean id="simpleTrigger"
  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
  <property name="jobDetail" ref="methodInvocationConfig" />
  <property name="repeatInterval" value="1000" />
  <property name="repeatCount" value="3" />
 </bean>

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

</beans>


Now, just load this Spring configuration file and check if task method gets invoked.

Main Client:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package in.blogspot.ashish4java.simplespringquartzexample;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainClient {

 public static void main(String[] args) {

  new ClassPathXmlApplicationContext("spring.xml");

 }

}

Result:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Sep 23, 2016 11:45:48 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1099f62: startup date [Fri Sep 23 23:45:48 IST 2016]; root of context hierarchy
Sep 23, 2016 11:45:48 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Sep 23, 2016 11:45:49 PM org.springframework.context.support.DefaultLifecycleProcessor start
INFO: Starting beans in phase 2147483647
Sep 23, 2016 11:45:49 PM org.springframework.scheduling.quartz.SchedulerFactoryBean startScheduler
INFO: Starting Quartz Scheduler now
Task execution in progress...
Task execution in progress...
Task execution in progress...
Task execution in progress...

We scheduled job to be repeated 3 times plus original execution so total job was executed 4 times with delay of 1 seconds between each run.

This is very simple method invocation job scheduler using Spring and Quartz. But if we need to pass some parameters to job or trigger jobs based on exact date/time then we need to use more complex job scheduler which we will see in next tutorial.