In this tutorial we will write simple Hello World application using Spring Batch 2.0. This is an introductory tutorial to Spring Batch.
Spring Batch Introduction-
Many applications within the enterprise domain require bulk processing to perform business critical operations. These business operations include automated, complex processing of large volumes of information that is most efficiently processed without user intervention.
Some Batch Terminologies-
Before we look into the details of Spring Batch, lets look at some important terms that will be used in this article and anywhere in context of Spring Batch. You have to read the following post.
1. Configuring and running jobs
2. Configuring Steps
3. ItemReader & ItemWriter
4. Some Domain Params
5. Read Spring Batch Terms
Spring Batch is a lightweight batch framework which enables the development of a batch applications for the daily operations of enterprise systems.
In this example, we will be explaining Spring Batch classes and interfaces using a simple Hello World example. We will create a job which consists of two steps. One prints “Hello World!” and second prints “Created By Dinesh On Java”. Aim is to keep the example simple and still understand the power of Spring Batch Framework.
Create Application Context XML-
In order to run Spring Batch, we need to configuration Spring Batch Infrastructure. This includes creation of JobRepository, JobLauncher and TransactionManager.
For each job, we will use a separate xml context definition file. However there is a number of common objects that we will need recurrently. I will group them in an applicationContext.xml which will be imported from within job definitions. Let’s go through these common objects:
JobLauncher-
JobLaunchers are responsible for starting a Job with a given job parameters. The provided implementation, SimpleJobLauncher, relies on a TaskExecutor to launch the jobs. If no specific TaskExecutor is set then a SyncTaskExecutor is used.
JobRepository-
We will use the SimpleJobRepository implementation which requires a set of execution Daos to store its information.
JobInstanceDao, JobExecutionDao, StepExecutionDao-
These data access objects are used by SimpleJobRepository to store execution related information. Two sets of implementations are provided by Spring Batch: Map based (in-memory) and Jdbc based. In a real application the Jdbc variants are more suitable but we will use the simpler in-memory alternative in this example.
Here’s our applicationContext.xml:
<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <import resource="MEMORY-JOBREPOSITORY.xml"/> </beans>
Here’s our MEMORY-JOBREPOSITORY.xml:
<beans xmlns:batch="http://www.springframework.org/schema/batch" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <bean class="org.springframework.batch.core.repository.support.SimpleJobRepository" id="jobRepository"> <constructor-arg><bean class="org.springframework.batch.core.repository.dao.MapJobInstanceDao"/> </constructor-arg><constructor-arg>bean class="org.springframework.batch.core.repository.dao.MapJobExecutionDao" /> </constructor-arg><constructor-arg><bean class="org.springframework.batch.core.repository.dao.MapStepExecutionDao"/> </constructor-arg><constructor-arg><bean class="org.springframework.batch.core.repository.dao.MapExecutionContextDao"/> </constructor-arg></bean> <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/> <bean class="org.springframework.batch.core.launch.support.SimpleJobLauncher" id="jobLauncher"> <property name="jobRepository" ref="jobRepository"/> </bean> </beans>
Create HelloWorldTasklet.java class-
A tasklet is a class containing custom logic to be run as a part of a job. HelloWorldTasklet is our custom tasklet which implements Tasklet interface and overrides the execute() method. It is a simple tasklet that simply prints a message.
Note that the execute method returns RepeatStatus to indicate execution status of tasklet.
RepeatStatus.FINISHED indicates that processing is finished (either successful or unsuccessful)
RepeatStatus.CONTINUABLE indicates that processing can continue.
package com.dineshonjava.batch.hello; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; /** * * @author Dinesh Rajput * */ public class HelloWorldTasklet implements Tasklet { private String message; public void setMessage(String message) { this.message = message; } @Override public RepeatStatus execute(StepContribution contribution, ChunkContext context) throws Exception { System.out.println(message); return RepeatStatus.FINISHED; } }
Create Job Configuration XML-
In this section we will see configuration to fit the custom tasklet into the Spring Batch framework.
<beans xmlns:batch="http://www.springframework.org/schema/batch" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <import resource="applicationContext.xml"/> <bean abstract="true" class="org.springframework.batch.core.step.tasklet.TaskletStep" id="taskletStep"> <property name="jobRepository" ref="jobRepository"/> <property name="transactionManager" ref="transactionManager"/> </bean> <bean class="com.dineshonjava.batch.hello.HelloWorldTasklet" id="helloTasklet"> <property name="message" value="Hello World!"/> </bean> <bean class="com.dineshonjava.batch.hello.HelloWorldTasklet" id="createdByTasklet"> <property name="message" value="Created By Dinesh On Java"/> </bean> <bean class="org.springframework.batch.core.job.SimpleJob" id="mySimpleJob"> <property name="name" value="mySimpleJob" /> <property name="steps"> <list> <bean parent="taskletStep"> <property name="tasklet" ref="helloTasklet"/> </bean> <bean parent="taskletStep"> <property name="tasklet" ref="createdByTasklet"/> </bean> </list> </property> <property name="jobRepository" ref="jobRepository"> </bean> </beans>
First we created an abstract bean (“taskletStep“) using class TaskletStep. We injected job repository and transaction manager into this tasklet. Later we created two instance of our HelloWorldTasklet class, one of which takes “Hello World!” as message and another takes “Created By Dinesh On Java” as message.
Finally we defined our batch job (“mySimpleJob“) consisting of two steps using class SimpleJob. Property “steps” takes list of tasklet steps which will be executed sequentially one after another.
As the two tasklet instances which we created earlier represent a step in our batch application, they use taskletStep abstract bean as parent.
Running the Job-
Now we need something to kick-start the execution of our jobs. Spring Batch provides a convenient class to achieve that from the command line: CommandLineJobRunner. In its simplest form this class takes 2 arguments:
1. the xml application context containing the job to launch(simpleJob.xml) and
2. the bean id of that job(mySimpleJob).
It naturally requires a JobLauncher to be configured in the application context.
First right click to project “springBatch2HelloWorld” and click on Run As and go to Run Configurations… as follows…
After clicking on the Run Configurations… we get the following window and put the information as on Project field with value “springBatch2HelloWorld” and Main Class field with value “org.springframework.batch.core.launch.support.CommandLineJobRunner”
Now switch to Arguments tabs on the above window we get the following window and put the value on the Program arguments as “config/simpleJob.xml mySimpleJob“. and click on the Run button.
After clicking Run button if every thing is Ok then we will get the following output on the console.
Jan 15, 2013 12:00:27 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1100d7a: startup date [Tue Jan 15 00:00:27 IST 2013]; root of context hierarchy
Jan 15, 2013 12:00:27 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/simpleJob.xml]
Jan 15, 2013 12:00:27 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/applicationContext.xml]
Jan 15, 2013 12:00:27 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/MEMORY-JOBREPOSITORY.xml]
Jan 15, 2013 12:00:27 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d85f79: defining beans [jobRepository,transactionManager,jobLauncher,taskletStep,helloTasklet,createdByTasklet,mySimpleJob]; root of factory hierarchy
Jan 15, 2013 12:00:27 AM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jan 15, 2013 12:00:27 AM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [SimpleJob: [name=mySimpleJob]] launched with the following parameters: [{}]
Jan 15, 2013 12:00:27 AM org.springframework.batch.core.job.AbstractJob handleStep
INFO: Executing step: [TaskletStep: [name=taskletStep$child#1ea5671]]
Hello World!
Jan 15, 2013 12:00:27 AM org.springframework.batch.core.job.AbstractJob handleStep
INFO: Executing step: [TaskletStep: [name=taskletStep$child#1d15445]]
Created By Dinesh On Java
Jan 15, 2013 12:00:27 AM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [SimpleJob: [name=mySimpleJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
Jan 15, 2013 12:00:27 AM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@1100d7a: startup date [Tue Jan 15 00:00:27 IST 2013]; root of context hierarchy
Jan 15, 2013 12:00:27 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1d85f79: defining beans [jobRepository,transactionManager,jobLauncher,taskletStep,helloTasklet,createdByTasklet,mySimpleJob]; root of factory hierarchy
Download SourceCode+Libs