Spring Batch - Hello World
This is an introductory tutorial to Spring Batch. It does not aim to provide a complete guide to the framework but rather to facilitate the first contact. Spring Batch is quite rich in functionalities, and this is basically how I started learning it. Keep in mind that we will only be scratching the surface.
Before we start
All the examples will have the lofty task of printing "Hello World!" though in different ways. They were developed with Spring Batch 1.0. I'll provide a Maven 2 project and I'll run the examples with Maven but of course it is not a requirement to work with Spring Batch.
Spring Batch in 2 Words
Fortunately, Spring Batch model objects have self-explanatory names. Let's try to enumerate the most important and to link them together:
A batch Job is composed of one or more Steps. A JobInstance represents a given Job, parametrized with a set of typed properties called JobParameters. Each run of of a JobInstance is a JobExecution. Imagine a job reading entries from a data base and generating an xml representation of it and then doing some clean-up. We have a Job composed of 2 steps: reading/writing and clean-up. If we parametrize this job by the date of the generated data then our Friday the 13th job is a JobInstance. Each time we run this instance (if a failure occurs for instance) is a JobExecution. This model gives a great flexibility regarding how jobs are launched and run. This naturally brings us to launching jobs with their job parameters, which is the responsibility of JobLauncher. Finally, various objects in the framework require a JobRepository to store runtime information related to the batch execution. In fact, Spring Batch domain model is much more elaborate but this will suffice for our purpose.
Well, it took more than 2 words and I feel compelled to make a joke about it, but I won't. So let's move to the next section.
Common Objects
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="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.SimpleJobRepository">
<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>
</bean>
</beans>
Hello World with Tasklets
A tasklet is an object containing any custom logic to be executed as a part of a job. Tasklets are built by implementing the Tasklet interface. Let's implement a simple tasklet that simply prints a message:
public class PrintTasklet implements Tasklet{
private String message;
public void setMessage(String message) {
this.message = message;
}
public ExitStatus execute() throws Exception {
System.out.print(message);
return ExitStatus.FINISHED;
}
}
Notice that the execute method returns an ExitStatus to indicate the status of the execution of the tasklet.
We will define our first job now in a simpleJob.xml application context. We will use the SimpleJob implementation which executes all of its steps sequentailly. In order to plug a tasklet into a job, we need a TaskletStep. I also added an abstract bean definition for tasklet steps in order to simplify the configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="applicationContext.xml"/>
<bean id="hello" class="helloworld.PrintTasklet">
<property name="message" value="Hello"/>
</bean>
<bean id="space" class="helloworld.PrintTasklet">
<property name="message" value=" "/>
</bean>
<bean id="world" class="helloworld.PrintTasklet">
<property name="message" value="World!"/>
</bean>
<bean id="taskletStep" abstract="true"
class="org.springframework.batch.core.step.tasklet.TaskletStep">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob">
<property name="name" value="simpleJob" />
<property name="steps">
<list>
<bean parent="taskletStep">
<property name="tasklet" ref="hello"/>
</bean>
<bean parent="taskletStep">
<property name="tasklet" ref="space"/>
</bean>
<bean parent="taskletStep">;
<property name="tasklet" ref="world"/>
</bean>
</list>
</property>
<property name="jobRepository" ref="jobRepository"/>
</bean>
</beans>
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: the xml application context containing the job to launch and the bean id of that job. It naturally requires a JobLauncher to be configured in the application context. Here's how to launch the job with Maven. Of course, it can be run with the java command directly (you need to specify the class path then):
mvn exec:java -Dexec.mainClass=org.springframework.batch.core.launch.support.CommandLineJobRunner
-Dexec.args="simpleJob.xml simpleJob"
Hopefully, your efforts will be rewarded with a "Hello World!" printed on the console.
The code source can be downloaded here.
What's Next?
This is the first part of 3. In the next part we will improve on this example while the third part will be dedicated to item oriented steps and flat files readers and writers. Hope you find it useful.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Alexander Shvets replied on Fri, 2008/05/23 - 9:00am
Nice introduction. Why do you have runtime scope in your pom file? I had to comment them in order to run the example.
Do you know if there is a way to "substitute" job execution with another implementation, like Quartz job scheduling system?
Tareq Abedrabbo replied on Fri, 2008/05/23 - 2:26pm
Joergen Larsen replied on Sat, 2008/05/24 - 3:54am
Thanks Tareq Abed, greate introduction - looking forward to next part.
Tareq Abedrabbo replied on Sat, 2008/05/24 - 10:38am
in response to:
Joergen Larsen
Paul Hill replied on Wed, 2008/06/04 - 11:33am
Typo on line 3 of applicationContext.xml and simpleJob.xml
xsi:schemaLocation="http://.../beanshttp://www..../spring-beans-2.5.xsd">
needs a space after bean and before http:
Typo on line 34 simpleJob.xml
<bean parent="taskletStep">;
Drop the semicolon
Typo in helloworld.PrintTasklet
since the job.xml file refers to helloworld.PrintTasklet the java file ought to put it in the right package.
add the line
package helloworld;
to PrintTasklet.java
-Paul
Simni Mama replied on Wed, 2009/04/08 - 2:45am
I have been trying to run this command on Command Line:
mvn exec:java -Dexec.mainClass=org.springframework.batch.core.launch.support.CommandLineJobRunner -Dexec.args="simpleJob.xml simpleJob"
but get the following error:
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] org.apache.maven.plugins: checking for updates from central
[WARNING] repository metadata for: 'org.apache.maven.plugins' could not be retri
eved from repository: central due to an error: Error transferring file
[INFO] Repository 'central' will be blacklisted
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin 'org.apache.maven.plugins:maven-exec-plugin' does not exist or
no valid version could be found
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Wed Apr 08 09:23:27 GMT+02:00 2009
[INFO] Final Memory: 1M/2M
[INFO] ------------------------------------------------------------------------
Please help as soon as possible.
Jeremy Leipzig replied on Wed, 2009/04/08 - 4:08pm
I couldn't see the hello world unless I redirected the output to a file
maven is very strange
victor joshua replied on Wed, 2009/10/21 - 11:51pm
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] org.apache.maven.plugins: checking for updates from central
[WARNING] repository metadata for: 'org.apache.maven.plugins' could not be retrieved from repository: central due to an error
: Error transferring file
[INFO] Repository 'central' will be blacklisted
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin 'org.apache.maven.plugins:maven-exec-plugin' does not exist or no valid version could be found
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: < 1 second
[INFO] Finished at: Wed Oct 21 19:27:04 IST 2009
[INFO] Final Memory: 1M/2M
[INFO] ------------------------------------------------------------------------
PLEASE HELP.
THANKS IN ADVANCE.
Juan Uys replied on Mon, 2010/02/08 - 10:12am
Md Khan replied on Fri, 2010/04/23 - 5:13am
Deepak Mohanakr... replied on Sun, 2011/07/03 - 11:30pm
Dear Tareq,
I am good at Spring framework. I just started exploring Spring Batch recently. I looked at your very useful and simple HelloWorld example. Thanks a ton for it. Could you please let me know how to achieve parallel processing in Spring Batch. I mean If I want to run the above three simple tasklets 10000 times parallaly in 20 threads. How to achieve it. I keep exploring Spring batch. But if you could answer could accelerate me in this regard.
Many Thanks,
Deepak
James Walker replied on Wed, 2012/06/20 - 7:30am
Lucifer Williams replied on Fri, 2012/11/16 - 1:37pm