Quartz Scheduler Spring

Quartz Scheduler Spring

In previous tutorial you saw a simple example of Quartz scheduler with Spring application and we were not using full functionality of spring to control the jobs. In this tutorial you will see how to control Quartz scheduling and execution from spring context file. Main reason of using this advance configuration is, you don’t need to write any Quartz related java code and everything is configurable through spring context file.

  • Create maven project name: QuartzSpringScheduler as below is snap shot of final structure:

Quartz Scheduler Spring

  • 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.javahonk</groupId>
	<artifactId>QuartzSpringScheduler</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<properties>
		<org.springframework.version>4.1.5.RELEASE</org.springframework.version>
		<org.apache.log4j.version>2.1</org.apache.log4j.version>
	</properties>

	<dependencies>
	
		<!-- Application Context (depends on spring-core, spring-expression, spring-aop, 
			spring-beans) This is the central artifact for Spring's Dependency Injection 
			Container and is generally always defined -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>

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

		<!-- Quartz scheduler -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.1.7</version>
		</dependency>

		<!-- Log4j -->
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>${org.apache.log4j.version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>${org.apache.log4j.version}</version>
		</dependency>		

	</dependencies>
</project>
  • log4j2.xml: Will be using logging as well:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">

	<Properties>
		<Property name="envrionment.target">DEV</Property>
	</Properties>

	<Properties>
		<Property name="logging.dir">./</Property>
	</Properties>

	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</Console>

		<RollingFile name="RollingFile"
			fileName="./log/javahonk/rolling-file.log"	filePattern="${sys:logging.dir}/logs/rolling-file-%d{yyyy-MM-dd}-%i.log">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
			<!-- TODO:Change to time based policy -->
			<Policies>
				<TimeBasedTriggeringPolicy interval="1"	modulate="true" />
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<DefaultRolloverStrategy max="4" />
		</RollingFile>
	</Appenders>

	<Loggers>
		<Root level="info">
			<AppenderRef ref="Console" />
			<!-- <AppenderRef ref="file" /> -->
			<AppenderRef ref="RollingFile" />
		</Root>
	</Loggers>
</Configuration>
  • spring-context.xml: Here is all configuration related to Quartz scheduler as explained through the diagram:

Quartz Scheduler Spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">

	<context:annotation-config />
	
	<context:component-scan base-package="com.javahonk" />

	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>Cron-Schedule.properties</value>
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" />
	</bean>

	<bean id="cronQuartzJob" class="com.javahonk.CronQuartzJob" />

	<bean id="cronQuartzJobScheduler" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="cronQuartzJob" />
		<property name="targetMethod" value="executeScheduleJob" />
	</bean>

	<bean id="cronQuartzJobSchedulerCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="cronQuartzJobScheduler" />
		<property name="cronExpression" value="${cron.schedule.time}" />
	</bean>

	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
				<ref bean="cronQuartzJobSchedulerCronTrigger" />
			</list>
		</property>
		
		<!-- You can control number of thread you want to run from below -->
		<property name="quartzProperties">
			<props>
				<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
				<prop key="org.quartz.threadPool.threadCount">1</prop>
			</props>
		</property>
	</bean>

</beans>
  • Cron-Schedule.properties: I have creates separate properties file from where you could control job run time:
#Cron scheduler run every minute
cron.schedule.time= 0/10 * * ? * MON-SUN *

#Run job every minute: 0 0/1 * 1/1 * ? *
#Run job everyday at 16:00 PM: 0 00 18 1/1 * ? *
#Run job everyday at multiple time start from 16:01,16:02... 21:01,21:02 etc..: 0 00,01,02,03 18,19,20,21 1/1 * ? *
#Run job every 15 minute: 0 0/15 * 1/1 * ? *

If it is your first time configuration with Cron scheduler as you don’t understand Cron time please visit CronMaker to understand it better.

  • CronQuartzJob.java: This is sample class with one method which will be called every schedule time:
package com.javahonk;

import java.time.LocalDateTime;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.JobExecutionException;

/**
 * @author Java Honk
 *
 */
public class CronQuartzJob {
	
	private static final Logger LOGGER = LogManager.getLogger(CronQuartzJob.class.getName());
	
	public void executeScheduleJob() throws JobExecutionException {
		
		//Write your code logic based on the schedule
		LOGGER.info("Cron Quartz Job started at time: {}", LocalDateTime.now());		
		
	}

}
  • CronQuartzJobTestApp.java: Main class to run Spring application and I have included method name: registerShutdownHook to keep thread alive:
package com.javahonk;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Java Honk
 *
 */
public class CronQuartzJobTestApp {
	
	private static final Logger LOGGER = LogManager.getLogger(CronQuartzJobTestApp.class.getName());
	
	public static void main(String[] args) {
		
		LOGGER.info("Application starting...");	
		
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
		
		registerShutdownHook(context);
	}
	
	private static void registerShutdownHook(ApplicationContext context) {
		
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

			@Override
			public void run() {
				LOGGER.info("Application Exiting.");
				((AbstractApplicationContext) context).close();

			}
		}));
	}
	
}
  • That’s it. To run this application right click CronQuartzJobTestApp.java –> Run As –> Java Application. As scheduler has been configured to run every 10 seconds so it will go to CronQuartzJob class and call its method: executeScheduleJob and will print logging information on the console as below:

Quartz Scheduler Spring

download Download Project:  QuartzSpringScheduler

Leave a Reply

Your email address will not be published. Required fields are marked *