This tutorial will show you how to read a csv file data and write to xml file with some modification. You can read the tutorial Spring Batch to read what is Spring Batch and what are the usages of Spring Batch.

What we will do

We’ll build a service that imports data from a CSV file, transforms it with custom code, and stores the final results in XML file.



Maven 3.2.1

JDK 1.8

Spring Batch and MySQL connector dependencies in pom.xml file

Step 1. Create Maven project(standalone or quickstart) in Eclipse IDE and necessary project structure gets created

Group Id: com.roytuts

Artifact Id: spring-batch

Step 2. Modify pom.xml file so that it looks like below. It downloads all jars from maven repository.

<project xmlns="" xmlns:xsi=""




		<!-- spring core -->

		<!-- spring context -->

		<!-- spring batch -->

		<!-- spring XML to Java or vice versa -->

		<!-- spring jdbc -->

		<!-- mysql driver -->



Step 3. Create a model class which will represent a row of data for inputs and outputs. I have made the below class JAXB annotation enabled for converting Java object to XML file directly.

package com.roytuts.spring.batch.model;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "person")
public class Person {

	private int id;
	private String firstName;
	private String lastName;

	@XmlAttribute(name = "id")
	public int getId() {
		return id;

	public void setId(int id) { = id;

	@XmlElement(name = "firstName")
	public String getFirstName() {
		return firstName;

	public void setFirstName(String firstName) {
		this.firstName = firstName;

	@XmlElement(name = "lastName")
	public String getLastName() {
		return lastName;

	public void setLastName(String lastName) {
		this.lastName = lastName;

	public String toString() {
		return "Person [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";


Step 4. Create below mapper class which will map the CSV file row item to Java object.

package com.roytuts.spring.batch.mapper;

import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;

import com.roytuts.spring.batch.model.Person;

public class PersonFieldSetMapper implements FieldSetMapper<Person> {

	public Person mapFieldSet(FieldSet fieldSet) throws BindException {
		Person person = new Person();
		return person;


Step 5. Create an intermediate processor. A common paradigm in batch processing is to ingest data, transform it, and then pipe it out somewhere else. Here we write a simple transformer that converts the initial characters of the names to uppercase.

package com.roytuts.spring.batch.processor;

import org.springframework.batch.item.ItemProcessor;

import com.roytuts.spring.batch.model.Person;

public class PersonItemProcessor implements ItemProcessor<Person, Person> {

	public Person process(Person person) throws Exception {
		System.out.println("Processing: " + person);
		final String initCapFirstName = person.getFirstName().substring(0, 1).toUpperCase()
				+ person.getFirstName().substring(1);
		final String initCapLastName = person.getLastName().substring(0, 1).toUpperCase()
				+ person.getLastName().substring(1);
		Person transformedPerson = new Person();
		return transformedPerson;


Step 6. Create below CSV file under src/main/resources directory


Step 7. Create below spring config XML files under src/main/resources directory


This file defines beans for Person class and PersonItemProcessor class.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""
	xmlns:xsi="" xmlns:context=""

	<bean id="person" class="com.roytuts.spring.batch.model.Person"
		scope="prototype" />

	<bean id="itemProcessor" class="com.roytuts.spring.batch.processor.PersonItemProcessor"
		scope="prototype" />



This file defines the bean for spring datasource. It also initializes the database for automatically creating spring batch job meta tables in MySQL database.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""
	xmlns:jdbc="" xmlns:xsi=""
	xmlns:p="" xmlns:aop=""
	xmlns:jee="" xmlns:tx=""

	<bean id="dataSource"
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/roytuts" />
		<property name="username" value="root" />
		<property name="password" value="" />

	<!-- create job-meta tables automatically -->
	<jdbc:initialize-database data-source="dataSource">
		<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
		<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />



This files defines beans for spring batch job, csv file reader, xml file writer, jaxb marshaller, job repository, transaction manager, job launcher.

A default simple implementation of the Job interface is provided by Spring Batch in the form of the SimpleJob class which creates some standard functionality on top of Job, however the batch namespace abstracts away the need to instantiate it directly.

A Step is a domain object that encapsulates an independent, sequential phase of a batch job. Therefore, every Job is composed entirely of one or more steps. A Step contains all of the information necessary to define and control the actual batch processing.

ItemReader is an abstraction that represents the retrieval of input for a Step, one item at a time.

ItemWriter is an abstraction that represents the output of a Step, one batch or chunk of items at a time. Generally, an item writer has no knowledge of the input it will receive next, only the item that was passed in its current invocation.

ItemProcessor is an abstraction that represents the business processing of an item. While the ItemReader reads one item, and the ItemWriter writes them, the ItemProcessor provides access to transform or apply other business processing. If, while processing the item, it is determined that the item is not valid, returning null indicates that the item should not be written out.

transaction-manager – Spring’s PlatformTransactionManager that will be used to begin and commit transactions during processing.

commit-interval – The number of items that will be processed before the transaction is committed.

The Tasklet is a simple interface that has one method, execute, which will be a called repeatedly by the TaskletStep until it either returns RepeatStatus.FINISHED or throws an exception to signal a failure. Each call to the Tasklet is wrapped in a transaction. Tasklet implementors might call a stored procedure, a script, or a simple SQL update statement. To create a TaskletStep, the ‘ref’ attribute of the <tasklet/> element should reference a bean defining a Tasklet object; no <chunk/> element should be used within the <tasklet/>

JobRepository is the persistence mechanism. It provides CRUD operations for JobLauncher, Job, and Step implementations. When a Job is first launched, a JobExecution is obtained from the repository, and during the course of execution StepExecution and JobExecution implementations are persisted by passing them to the repository.

JobLauncher represents a simple interface for launching a Job with a given set of JobParameters.

A batch namespace has been provided for ease of configuration and as long as the batch namespace has been declared, any of its elements can be used.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns=""
	xmlns:beans="" xmlns:xsi=""

	<beans:import resource="classpath:spring-datasource.xml" />
	<beans:import resource="classpath:spring-beans.xml" />

	<job id="ioSampleJob">
		<step id="step1">
			<tasklet transaction-manager="transactionManager">
				<chunk reader="cvsFileItemReader" writer="xmlItemWriter"
					processor="itemProcessor" commit-interval="2" />

	<beans:bean id="cvsFileItemReader"
		<beans:property name="resource" value="classpath:person.csv" />
		<beans:property name="lineMapper">
				<beans:property name="lineTokenizer">
						<beans:property name="names" value="id,firstName,lastName" />
				<beans:property name="fieldSetMapper">
					<beans:bean class="com.roytuts.spring.batch.mapper.PersonFieldSetMapper" />

	<beans:bean id="xmlItemWriter"
		<beans:property name="resource" value="file:xml/person.xml" />
		<beans:property name="marshaller" ref="personMarshaller" />
		<beans:property name="rootTagName" value="personInfo" />

	<beans:bean id="personMarshaller"
		<beans:property name="classesToBeBound">

	<!-- stored job-meta in database -->
	<beans:bean id="jobRepository"
		<beans:property name="dataSource" ref="dataSource" />
		<beans:property name="transactionManager" ref="transactionManager" />
		<beans:property name="databaseType" value="mysql" />

	<beans:bean id="transactionManager"
		class="" />

	<beans:bean id="jobLauncher"
		<beans:property name="jobRepository" ref="jobRepository" />


Step 8. Create below class for launching spring batch job.

package com.roytuts.spring.batch.runner;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;

public class SpringBatchRunner {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "spring-batch.xml" });

		JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
		Job job = (Job) context.getBean("ioSampleJob");

		try {
			JobExecution execution =, new JobParameters());
			System.out.println("Job Status : " + execution.getStatus());
		} catch (Exception ex) {



Step 9. Run the above class, you will see the below output.

Jan 14, 2017 5:50:54 PM prepareRefresh
INFO: Refreshing startup date [Sat Jan 14 17:50:54 IST 2017]; root of context hierarchy
Jan 14, 2017 5:50:54 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-batch.xml]
Jan 14, 2017 5:50:55 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-datasource.xml]
Jan 14, 2017 5:50:55 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-beans.xml]
Jan 14, 2017 5:50:55 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: com.mysql.jdbc.Driver
Jan 14, 2017 5:50:55 PM org.springframework.jdbc.datasource.init.ScriptUtils executeSqlScript
INFO: Executing SQL script from class path resource [org/springframework/batch/core/schema-drop-mysql.sql]
Jan 14, 2017 5:50:56 PM org.springframework.jdbc.datasource.init.ScriptUtils executeSqlScript
INFO: Executed SQL script from class path resource [org/springframework/batch/core/schema-drop-mysql.sql] in 440 ms.
Jan 14, 2017 5:50:56 PM org.springframework.jdbc.datasource.init.ScriptUtils executeSqlScript
INFO: Executing SQL script from class path resource [org/springframework/batch/core/schema-mysql.sql]
Jan 14, 2017 5:50:56 PM org.springframework.jdbc.datasource.init.ScriptUtils executeSqlScript
INFO: Executed SQL script from class path resource [org/springframework/batch/core/schema-mysql.sql] in 882 ms.
Jan 14, 2017 5:50:57 PM org.springframework.oxm.jaxb.Jaxb2Marshaller createJaxbContextFromClasses
INFO: Creating JAXBContext with classes to be bound [class com.roytuts.spring.batch.model.Person]
Jan 14, 2017 5:50:57 PM afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jan 14, 2017 5:50:57 PM run
INFO: Job: [FlowJob: [name=ioSampleJob]] launched with the following parameters: [{}]
Jan 14, 2017 5:50:57 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing: Person [id=1000, firstName=soumitra, lastName=roy]
Processing: Person [id=1001, firstName=souvik, lastName=sanyal]
Processing: Person [id=1002, firstName=arup, lastName=chatterjee]
Processing: Person [id=1003, firstName=suman, lastName=mukherjee]
Processing: Person [id=1004, firstName=debina, lastName=guha]
Processing: Person [id=1005, firstName=liton, lastName=sarkar]
Processing: Person [id=1006, firstName=debabrata, lastName=poddar]
Jan 14, 2017 5:50:58 PM run
INFO: Job: [FlowJob: [name=ioSampleJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
Job Status : COMPLETED

In the above output you see the job name, step name and also which row item from csv file is being processed. You also see the sql scripts have been executed and below tables have been created in the MySQL database with job details.

spring batch tables

Thanks for reading.


I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

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