Java Batch Tutorial
1. Introduction
In this post, we feature a comprehensive Example on Java Batch. Java batch application is a Java application which processes a group of records, usually large volumes of data, as a single unit automatically. Spring introduced the Spring-batch framework in 2006. Spring Batch is an open source framework designed to enable the development of robust batch applications vital for the daily operations of enterprise systems. It has supported JSR 352 since version 3.0. In this example, I will demonstrate how to create a Java batch application in 15 minutes utilizing Spring Batch framework.
2. Technologies used
The example code in this article was built and run using:
- Java 1.8.101 (1.8.x will do fine)
- Maven 3.3.9 (3.3.x will do fine)
- Spring boot 1.5.14 ( Higher version will do fine)
- Spring Batch 3.0.5.RELEASE (4.0.0.M1 will do fine)
- Eclipse Mars (Any Java IDE would work)
3. Spring Boot Batch Application
The easiest way to generate a Spring-boot batch application is via the Spring starter tool with the steps below:
- Go to https://start.spring.io/.
- Select
Maven ProjectwithJavaand Spring Boot version 1.5.14 and type inBatch,H2in the “search for dependencies” bar. - Enter the group name as
jcg.demo.zhengand artifact asspringboot-batch-demo. - Click the
Generate Projectbutton.
A zip file – springboot-batch-demo.zip will be generated and downloaded to your workstation.
4. Eclipse Maven Project
In this step, I will import the generated Spring boot batch project into my Eclipse workspace with these steps:
- Unzip the
springboot-batch-demo.ziptoC:\MZheng_Java_workspace\spingboot-batch-demo. - Launch Eclipse.
- Click Import->Existing Maven Project.
- Browse to the
C:\MZheng_Java_workspace\spingboot-batch-demoand click Finish.
A maven project – springboot-batch-demo will be imported.
4.1 Maven Dependency
The generated pom.xml includes spring-boot-starter-batch and H2database. There is no modification needed in this example.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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>jcg.demo.zheng</groupId> <artifactId>springboot-batch-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-batch-demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
4.2 Spring Batch Application
The generated SpringbootBatchDemoApplication.java is annotated with @SpringBootApplication. It is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScanwith their default attributes.
In this step, I will add @EnableBatchProcessingto enable Batch auto-configuration. By default, it executes all Jobs in the application context on startup.
SpringbootBatchDemoApplication.java
package jcg.demo.zheng.springbootbatchdemo;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableBatchProcessing
public class SpringbootBatchDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootBatchDemoApplication.class, args);
}
}
5. Spring Batch Framework Overview
Spring batch framework defines a batch domain language. In this example, we will stick to these terms to avoid confusion. Please click here for more details.

A simplified architecture diagram above shows the key components. The blue ones are Spring Batch Beans; the yellow ones are Spring Batch interfaces. Developers implement the ItemReader, ItemWriter, and ItemProcessor interfaces based on the business processing logic. Then they wire them into batch Jobs and Steps. These batch jobs then will be executed by the Spring JobLauncher.
5.1 Batch Steps
According to the Batch Domain language, a Step is a domain object that encapsulates an independent, sequential phase of a batch job. A Step contains all of the information necessary to define and control the actual batch processing. In this step, I will create a Reader-Processor-Writer step which reads messages, converts them into an uppercase format, and then outputs them to the console.
5.1.1 SimpleReader
SimpleReader is a class which implements the ItemReader. It reads a list of String messages.
SimpleReader.java
package jcg.demo.zheng.springbootbatchdemo.step;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
public class SimpleReader implements ItemReader {
private String[] tenMessages = { "Message 1", "Message 2", "Message 3", "Message 4", "Message 5", "Message 6",
"Message 7", "Message 8", "Message 9", "Message 10" };
private int count = 0;
@Override
public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if (count < tenMessages.length) {
return tenMessages[count++];
} else {
count = 0;
}
return null;
}
}5.1.2 SimpleWriter
SimpleWriter is a class which implements the ItemWriter. It writes out String message.
SimpleWriter.java
package jcg.demo.zheng.springbootbatchdemo.step;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
public class SimpleWriter implements ItemWriter {
@Override
public void write(List<? extends String> messages) throws Exception {
for (String msg : messages) {
System.out.println("Writing the data " + msg);
}
}
}5.1.3 SimpleProcessor
SimpleProcessor is a class which implements the ItemProcessor. It converts the String message to the uppercase format.
SimpleProcessor.java
package jcg.demo.zheng.springbootbatchdemo.step;
import org.springframework.batch.item.ItemProcessor;
public class SimpleProcessor implements ItemProcessor<String, String> {
@Override
public String process(String data) throws Exception {
System.out.println("process for " + data);
return data.toUpperCase();
}
}
5.2 Batch Job Execution Listener
A JobExecution refers to the technical concept of a single attempt to run a Job. An execution may end in either failure or success. In this step, I will create a listener to output the job status after the job is executed.
JobCompletionListener.java
package jcg.demo.zheng.springbootbatchdemo.listener;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.stereotype.Component;
@Component
public class JobCompletionListener extends JobExecutionListenerSupport {
@Override
public void afterJob(JobExecution jobExecution) {
StringBuilder msg = new StringBuilder();
msg.append("##### Finishing Job Name=").append(jobExecution.getJobInstance().getJobName())
.append(" JOB_EXE_ID=").append(jobExecution.getId()).append(" JOB_ID=").append(jobExecution.getJobId())
.append(", Status=").append(jobExecution.getStatus()).append(", StartTime=")
.append(jobExecution.getStartTime()).append(", EndTime=").append(jobExecution.getEndTime());
System.out.println(msg);
}
}
5.3 Batch Job and Step Configuration
5.3.1 SimpleAdapterReader
SimpleAdapterReader is a class which implements the InitializingBean.
SimpleAdapterReader.java
package jcg.demo.zheng.springbootbatchdemo.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class SimpleAdapterReader implements InitializingBean {
private List messages = new ArrayList();
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("User bean initialized successfully...");
loadItems();
}
private void loadItems() throws Exception {
for (int i = 0; i 0) {
return messages.remove(0);
} else {
System.out.println("No more item to read");
return null;
}
}
}
A Job is an entity that encapsulates the entire batch process.
In this step, I will configure two Spring batch jobs – simpleJob and simpleAdapterJob:
- Wire
simpleJobwithoneStepwhich consists ofSimpleReader,SimpleWriter, andSimpleProcessorwith chunk sizes of three. - Wire
simpleAdapterJobwithadapterStepwhich containssimpleAdaperReader,SimpleWriter, andSimpleProcessorwith chunk sizes of three.
BatchConfig.java
package jcg.demo.zheng.springbootbatchdemo.config;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.adapter.ItemReaderAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jcg.demo.zheng.springbootbatchdemo.step.SimpleProcessor;
import jcg.demo.zheng.springbootbatchdemo.step.SimpleReader;
import jcg.demo.zheng.springbootbatchdemo.step.SimpleWriter;
@Configuration
public class BatchConfig {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public JobExecutionListener listener;
@Autowired
public SimpleAdapterReader simpleAdapter;
private int STEP_CHUNK_SIZE = 3;
private static final String SIMPLE_JOB_NAME = "simpleJob";
private static final String STEP_ONE_NAME = "oneStep";
private static final String STEP_A_NAME = "adapterStep";
@Bean
public Job simpleJob() {
return jobBuilderFactory.get(SIMPLE_JOB_NAME).incrementer(new RunIdIncrementer()).listener(listener)
.flow(oneStep()).end().build();
}
@Bean
public Job simpleAdapterJob() {
return jobBuilderFactory.get("simpleAdapterJob").incrementer(new RunIdIncrementer()).listener(listener)
.flow(adapterStep()).end().build();
}
@Bean
public Step oneStep() {
return stepBuilderFactory.get(STEP_ONE_NAME). chunk(STEP_CHUNK_SIZE).reader(new SimpleReader())
.processor(new SimpleProcessor()).writer(new SimpleWriter()).build();
}
@Bean
public Step adapterStep() {
return stepBuilderFactory.get(STEP_A_NAME). chunk(STEP_CHUNK_SIZE).reader(simpleAdaperReader())
.processor(new SimpleProcessor()).writer(new SimpleWriter()).build();
}
@Bean
public ItemReaderAdapter simpleAdaperReader() {
ItemReaderAdapter adapter = new ItemReaderAdapter();
adapter.setTargetObject(simpleAdapter);
adapter.setTargetMethod("nextItem");
return adapter;
}
}
6. Demo
Start the SpringbootBatchDemoApplication, we will see that both Batch jobs are executed.
SpringbootBatchDemoApplication Output
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.14.RELEASE)
2018-06-20 17:10:18.570 INFO 11712 --- [ main] j.d.z.s.SpringbootBatchDemoApplication : Starting SpringbootBatchDemoApplication on SL2LS431841 with PID 11712 (C:\MZheng_Java_workspace\springboot-batch-demo\target\classes started by Shu.Shan in C:\MZheng_Java_workspace\springboot-batch-demo)
2018-06-20 17:10:18.573 INFO 11712 --- [ main] j.d.z.s.SpringbootBatchDemoApplication : No active profile set, falling back to default profiles: default
2018-06-20 17:10:18.675 INFO 11712 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@27c6e487: startup date [Wed Jun 20 17:10:18 CDT 2018]; root of context hierarchy
User bean initialized successfully...
2018-06-20 17:10:21.054 INFO 11712 --- [ main] o.s.jdbc.datasource.init.ScriptUtils : Executing SQL script from class path resource [org/springframework/batch/core/schema-h2.sql]
2018-06-20 17:10:21.139 INFO 11712 --- [ main] o.s.jdbc.datasource.init.ScriptUtils : Executed SQL script from class path resource [org/springframework/batch/core/schema-h2.sql] in 83 ms.
2018-06-20 17:10:21.416 INFO 11712 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-06-20 17:10:21.443 INFO 11712 --- [ main] o.s.b.a.b.JobLauncherCommandLineRunner : Running default command line with: []
2018-06-20 17:10:21.461 INFO 11712 --- [ main] o.s.b.c.r.s.JobRepositoryFactoryBean : No database type set, using meta data indicating: H2
2018-06-20 17:10:21.820 INFO 11712 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : No TaskExecutor has been set, defaulting to synchronous executor.
2018-06-20 17:10:21.975 INFO 11712 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=simpleJob]] launched with the following parameters: [{run.id=1}]
2018-06-20 17:10:22.023 INFO 11712 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [oneStep]
process for Message 1
process for Message 2
process for Message 3
Writing the data MESSAGE 1
Writing the data MESSAGE 2
Writing the data MESSAGE 3
process for Message 4
process for Message 5
process for Message 6
Writing the data MESSAGE 4
Writing the data MESSAGE 5
Writing the data MESSAGE 6
process for Message 7
process for Message 8
process for Message 9
Writing the data MESSAGE 7
Writing the data MESSAGE 8
Writing the data MESSAGE 9
process for Message 10
Writing the data MESSAGE 10
##### Finishing Job Name=simpleJob JOB_EXE_ID=1 JOB_ID=1, Status=COMPLETED, StartTime=Wed Jun 20 17:10:21 CDT 2018, EndTime=Wed Jun 20 17:10:22 CDT 2018
2018-06-20 17:10:22.083 INFO 11712 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=simpleJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED]
2018-06-20 17:10:22.095 INFO 11712 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=simpleAdapterJob]] launched with the following parameters: [{run.id=1}]
2018-06-20 17:10:22.108 INFO 11712 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [adapterStep]
process for SimpleAdatperReader Message 0
process for SimpleAdatperReader Message 1
process for SimpleAdatperReader Message 2
Writing the data SIMPLEADATPERREADER MESSAGE 0
Writing the data SIMPLEADATPERREADER MESSAGE 1
Writing the data SIMPLEADATPERREADER MESSAGE 2
process for SimpleAdatperReader Message 3
process for SimpleAdatperReader Message 4
process for SimpleAdatperReader Message 5
Writing the data SIMPLEADATPERREADER MESSAGE 3
Writing the data SIMPLEADATPERREADER MESSAGE 4
Writing the data SIMPLEADATPERREADER MESSAGE 5
process for SimpleAdatperReader Message 6
process for SimpleAdatperReader Message 7
process for SimpleAdatperReader Message 8
Writing the data SIMPLEADATPERREADER MESSAGE 6
Writing the data SIMPLEADATPERREADER MESSAGE 7
Writing the data SIMPLEADATPERREADER MESSAGE 8
process for SimpleAdatperReader Message 9
process for SimpleAdatperReader Message 10
process for SimpleAdatperReader Message 11
Writing the data SIMPLEADATPERREADER MESSAGE 9
Writing the data SIMPLEADATPERREADER MESSAGE 10
Writing the data SIMPLEADATPERREADER MESSAGE 11
process for SimpleAdatperReader Message 12
process for SimpleAdatperReader Message 13
process for SimpleAdatperReader Message 14
Writing the data SIMPLEADATPERREADER MESSAGE 12
Writing the data SIMPLEADATPERREADER MESSAGE 13
Writing the data SIMPLEADATPERREADER MESSAGE 14
process for SimpleAdatperReader Message 15
process for SimpleAdatperReader Message 16
process for SimpleAdatperReader Message 17
Writing the data SIMPLEADATPERREADER MESSAGE 15
Writing the data SIMPLEADATPERREADER MESSAGE 16
Writing the data SIMPLEADATPERREADER MESSAGE 17
No more item to read
process for SimpleAdatperReader Message 18
process for SimpleAdatperReader Message 19
Writing the data SIMPLEADATPERREADER MESSAGE 18
Writing the data SIMPLEADATPERREADER MESSAGE 19
##### Finishing Job Name=simpleAdapterJob JOB_EXE_ID=2 JOB_ID=2, Status=COMPLETED, StartTime=Wed Jun 20 17:10:22 CDT 2018, EndTime=Wed Jun 20 17:10:22 CDT 2018
2018-06-20 17:10:22.148 INFO 11712 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=simpleAdapterJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED]
2018-06-20 17:10:22.150 INFO 11712 --- [ main] j.d.z.s.SpringbootBatchDemoApplication : Started SpringbootBatchDemoApplication in 4.066 seconds (JVM running for 5.163)
2018-06-20 17:10:22.150 INFO 11712 --- [ Thread-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@27c6e487: startup date [Wed Jun 20 17:10:18 CDT 2018]; root of context hierarchy
2018-06-20 17:10:22.153 INFO 11712 --- [ Thread-3] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
7. Summary
In this example, we demonstrated how to build a Java batch application with Spring Batch framework in five steps:
- Generate the Spring boot batch application.
- Import the generated project into Eclipse IDE.
- Create implementation classes for Spring Batch
ItemReader,ItemWriter, andItemProcessorInterfaces. - Configure the Spring batch
JobandStepwith Java based configuration. - Start the Spring boot application to execute Spring batch jobs.
8. Download the Source Code
This example consists of a Java Batch application.
You can download the full source code of this example here: springboot-batch-demo




SimpleWriter, SimpleAdapterReader classes not matching the code.