Spring Batch TaskScheduler Example

Why do we need scheduling?
Scheduling is needed if you want to automate the repetition of a task at specific intervals or particular date. You could of course manually watch the time and execute your task, albeit an inefficient task. Who wants to watch the computer every 10 seconds just to hit the Enter key? No one.


In this example we use a simple configuration and an example implementation of ItemReader and ItemWriter, as you can see below. The Job is defined to run every 10 seconds. While everything works well in the first iteration, reading and writing seems to be skipped in the subsequent iterations.
<batch:job id="simpleDojJob" parent="simpleJob">
     <batch:step id="step1">
      <batch:tasklet>
       <batch:chunk reader="xmlItemReader" writer="mongodbItemWriter" commit-interval="2" processor="employeeFilter"/>
      </batch:tasklet>
     </batch:step>
    </batch:job>   
<bean id="runScheduler" class="com.doj.batch.scheduler.RunScheduler" />
 
  <!-- Run every 10 seconds -->
   <task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" cron="*/10 * * * * *" />
   </task:scheduled-tasks>

In this tutorial, we will show you how to use Spring TaskScheduler to schedule a batch job to run every 5 seconds.

Tools and libraries used
  • Spring Tool Suite (STS)
  • JDK 1.6
  • Spring Core 3.2.2.RELEASE
  • Spring OXM 3.2.2.RELEASE
  • Spring Batch 2.2.0.RELEASE
  • MongoDB Java Driver 2.7.3
  • MongoDB 2.10.1

1. Project Directory Structure

2. Spring TaskScheduler
Spring 3.0 introduces a TaskScheduler for scheduling tasks. It is part of the Spring-Core, no need to declare an extra dependency. A scheduler triggers launch Spring Batch jobs, by accessing the Spring Batch runtime.

<!-- Run every 10 seconds -->
   <task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" cron="*/10 * * * * *" />
   </task:scheduled-tasks>
  <task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" fixed-delay="10000" />
   </task:scheduled-tasks>

The TaskScheduler will schedule to run below bean.
package com.doj.batch.scheduler;

import java.util.Date;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Dinesh Rajput
 *
 */
@Component
public class RunScheduler {
 @Autowired
 private JobLauncher jobLauncher;
  
 @Autowired
 private Job job;
 
 public void run() {
     try {
   String dateParam = new Date().toString();
   JobParameters param = new JobParametersBuilder().addString("date", dateParam).toJobParameters();
   System.out.println(dateParam);
   JobExecution execution = jobLauncher.run(job, param);
   System.out.println("Exit Status : " + execution.getStatus());
     } catch (Exception e) {
      //e.printStackTrace();
     }
   }
}

Input XML File
employees.xml
s<?xml version="1.0" encoding="UTF-8"?>
<employees>
 <employee>
  <address>delhi</address>
  <age>37</age>
  <empid>1111</empid>
  <name>ATUL KUMAR</name>
  <salary>300000.0</salary>
 </employee>
 <employee>
  <address>delhi</address>
  <age>27</age>
  <empid>2222</empid>
  <name>Dinesh Rajput</name>
  <salary>60000.0</salary>
 </employee>
 <employee>
  <address>delhi</address>
  <age>31</age>
  <empid>3333</empid>
  <name>ASHUTOSH RAJPUT</name>
  <salary>400000.0</salary>
 </employee>
 <employee>
  <address>Kanpur</address>
  <age>27</age>
  <empid>4444</empid>
  <name>Adesh Verma</name>
  <salary>80000.0</salary>
 </employee>
 <employee>
  <address>Noida</address>
  <age>37</age>
  <empid>5555</empid>
  <name>Dinesh Rajput</name>
  <salary>300000.0</salary>
 </employee>
</employees>

Employee.java
package com.doj.batch.bean;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author Dinesh Rajput
 *
 */
@XmlRootElement(name="employee")
public class Employee {
 private int empid;
 private String name;
 private int age;
 private float salary;
 private String address;
 /**
  * @return the empid
  */
 public int getEmpid() {
  return empid;
 }
 /**
  * @param empid the empid to set
  */
 public void setEmpid(int empid) {
  this.empid = empid;
 }
 /**
  * @return the name
  */
 public String getName() {
  return name;
 }
 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }
 /**
  * @return the age
  */
 public int getAge() {
  return age;
 }
 /**
  * @param age the age to set
  */
 public void setAge(int age) {
  this.age = age;
 }
 /**
  * @return the salary
  */
 public float getSalary() {
  return salary;
 }
 /**
  * @param salary the salary to set
  */
 public void setSalary(float salary) {
  this.salary = salary;
 }
 /**
  * @return the address
  */
 public String getAddress() {
  return address;
 }
 /**
  * @param address the address to set
  */
 public void setAddress(String address) {
  this.address = address;
 }
 
 public String toString(){
  return "Name- "+name+" Age- "+age+" salary- "+salary+" address "+address;
 }
 
}

4. Job configuration
simple-job.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p" 
 xmlns:task="http://www.springframework.org/schema/task"
 xmlns:batch="http://www.springframework.org/schema/batch"
 xmlns:mvc="http://www.springframework.org/schema/mvc" 
 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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/batch 
http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
 <context:component-scan base-package="com.doj.batch" />
 <import resource="applicationContext.xml"/>
 <import resource="mongodbConfig.xml"/>
 
 <bean id="xmlItemReader" class="org.springframework.batch.item.xml.StaxEventItemReader">
  <property name="resource" value="classpath:xml/employees.xml" />
  <property name="unmarshaller" ref="empUnMarshaller" />
  <property name="fragmentRootElementName" value="employee" />
   </bean>
 <bean id="empUnMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
   <value>com.doj.batch.bean.Employee</value>
  </property>
   </bean>
 <!-- write it to MongoDB, 'employee' collection (table) -->
    <bean id="mongodbItemWriter" class="org.springframework.batch.item.data.MongoItemWriter">
  <property name="template" ref="mongoTemplate" />
  <property name="collection" value="employee" />
    </bean>
    
    <bean id="employeeFilter" class="com.doj.batch.process.EmployeeFilter"></bean>
    
    <batch:job id="simpleDojJob" parent="simpleJob">
     <batch:step id="step1">
      <batch:tasklet>
       <batch:chunk reader="xmlItemReader" writer="mongodbItemWriter" commit-interval="2" processor="employeeFilter"/>
      </batch:tasklet>
     </batch:step>
    </batch:job>   
    
    <bean id="runScheduler" class="com.doj.batch.scheduler.RunScheduler" />
 
  <!-- Run every 10 seconds -->
   <task:scheduled-tasks>
  <task:scheduled ref="runScheduler" method="run" cron="*/10 * * * * *" />
   </task:scheduled-tasks>
</beans>

Run It-
Loads the Spring application context, the scheduler will be run automatically.
TestBatch.java
package com.doj.batch.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Dinesh Rajput
 *
 */
public class TestBatch {

 /**
  * @param args
  */
 public static void main(String[] args) {
  ApplicationContext context = new ClassPathXmlApplicationContext("simple-job.xml");
 }

}

Output, it insert the xml content every 10 seconds in mongodb.

............
..............
Mar 9, 2014 5:43:18 PM org.springframework.oxm.jaxb.Jaxb2Marshaller createJaxbContextFromClasses
INFO: Creating JAXBContext with classes to be bound [class com.doj.batch.bean.Employee]
Sun Mar 09 17:43:20 IST 2014
Mar 9, 2014 5:43:20 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=simpleDojJob]] launched with the following parameters: [{date=Sun Mar 09 17:43:20 IST 2014}]
Mar 9, 2014 5:43:20 PM org.springframework.batch.core.job.AbstractJob handleStep
INFO: Executing step: [TaskletStep: [name=step1]]
Name- ATUL KUMAR Age- 37 salary- 300000.0 address delhi
Mar 9, 2014 5:43:20 PM org.springframework.oxm.jaxb.Jaxb2Marshaller processSource
Name- ASHUTOSH RAJPUT Age- 31 salary- 400000.0 address delhi
Mar 9, 2014 5:43:20 PM org.springframework.oxm.jaxb.Jaxb2Marshaller processSource
Name- Dinesh Rajput Age- 37 salary- 300000.0 address Noida
Exit Status : COMPLETED
Mar 9, 2014 5:43:20 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=simpleDojJob]] completed with the following parameters: [{date=Sun Mar 09 17:43:20 IST 2014}] and the following status: [COMPLETED]
Sun Mar 09 17:43:30 IST 2014
......................
...........................



Download Source Code with Jars
SpringBatchTaskSchedulerExample.zip









No comments:

Post a Comment