The previous part of my Spring Batch tutorial described how we can read information from a CSV File. This time we will learn to read the input data of our Spring Batch job from an XML file. After we have read this blog post, we:
- Can identify the dependencies which are required when we want to read the input data of our batch job from an XML file.
- Can get the required dependencies with Maven and Gradle.
- Understand how we can configure an
ItemReader
bean which reads the input data of our batch job from an XML file.
Let’s start by taking a quick look at our example application.
- You are familiar with Spring Batch
- You can get the required dependencies with Maven or Gradle
Introduction to Our Example Application
During this blog post we will read the input data of our batch job from an XML file which contains the student information of an online course. To be more specific, the XML file contains a student list that provides the following information to our batch job:
- The name of the student.
- The email address of the student.
- The name of the purchased package.
The content of our input file looks as follows:
<students> <student> <name>Tony Tester</name> <emailAddress>[email protected]</emailAddress> <purchasedPackage>master</purchasedPackage> </student> <student> <name>Nick Newbie</name> <emailAddress>[email protected]</emailAddress> <purchasedPackage>starter</purchasedPackage> </student> <student> <name>Ian Intermediate</name> <emailAddress>[email protected]</emailAddress> <purchasedPackage>intermediate</purchasedPackage> </student> </students>
The ItemReader
which reads the student list from an XML file must return StudentDTO
objects. A StudentDTO
class contains the information of a single student, and its source code looks as follows:
public class StudentDTO { private String emailAddress; private String name; private String purchasedPackage; public StudentDTO() {} public String getEmailAddress() { return emailAddress; } public String getName() { return name; } public String getPurchasedPackage() { return purchasedPackage; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public void setName(String name) { this.name = name; } public void setPurchasedPackage(String purchasedPackage) { this.purchasedPackage = purchasedPackage; } }
Next, we will get the required dependencies with Maven and Gradle.
Getting the Required Dependencies
Before we can read information from an XML file, we must get the following dependencies:
- The
spring-oxm
dependency helps us to serialize objects to XML documents and deserialize XML documents to objects. - The
jaxb-api
depedency allows us to compile code which uses the JAXB API when we are using Java 11 or newer. - The
jaxb-runtime
dependency allows us to run an application which uses the JAXB API when we are using Java 11 or newer.
If we are using the dependency management of Spring Boot with Maven, we can get these dependencies by adding the following dependency declarations to the dependencies
section of our POM file:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> </dependency>
If we are using the dependency management of Spring Boot with Gradle, we can get these dependencies by adding the following dependency declarations to our build.gradle file:
dependencies { implementation( 'javax.xml.bind:jaxb-api', 'org.springframework:spring-oxm' ) runtimeOnly( 'org.glassfish.jaxb:jaxb-runtime' ) }
Let’s move and find out how we can read the input data of our batch job from an XML file.
Reading the Input Data From an XML File
We can provide the input data for our batch job by configuring an ItemReader
bean. Because we want to read the student information from an XML file, we have to configure this bean by following these steps:
First, we have to create the configuration class which contains the beans that describe the flow of our batch job. The source code of our configuration class looks as follows:
import org.springframework.context.annotation.Configuration; @Configuration public class SpringBatchExampleJobConfig { }
Second, we have to create the method that configures our ItemReader
bean and ensure that this method returns an ItemReader<StudentDTO>
object. After we have created this method, the source code of our configuration class looks as follows:
import org.springframework.batch.item.ItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SpringBatchExampleJobConfig { @Bean public ItemReader<StudentDTO> itemReader() { } }
Third, we have to configure our ItemReader
bean by following these steps:
- Create a new
StaxEventItemReader<StudentDTO>
object. This object reads the input data from an XML file by using StAX (the Streaming API for XML). - Configure the location of the XML file which contains the input data of our batch job. Because I wanted to create an example application that’s as easy to run as possible, I ensured that the input file (data/students.xml) of our batch job is found from the classpath.
- Configure the name of the XML element (
student
) that contains the information of a single student. - Ensure that the
StaxEventItemReader<StudentDTO>
object transforms the processed XML fragment into aStudentDTO
object by using JAXB2. - Return the created
StaxEventItemReader<StudentDTO>
object.
After we have configured our ItemReader
bean, the source code of our configuration class looks as follows:
import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.xml.StaxEventItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.oxm.jaxb.Jaxb2Marshaller; @Configuration public class SpringBatchExampleJobConfig { @Bean public ItemReader<StudentDTO> itemReader() { StaxEventItemReader<StudentDTO> xmlFileReader = new StaxEventItemReader<>(); xmlFileReader.setResource(new ClassPathResource("data/students.xml")); xmlFileReader.setFragmentRootElementName("student"); Jaxb2Marshaller studentMarshaller = new Jaxb2Marshaller(); studentMarshaller.setClassesToBeBound(StudentDTO.class); xmlFileReader.setUnmarshaller(studentMarshaller); return xmlFileReader; } }
ClassPathResource
object because I wanted to create an example application that’s as easy to run as possible. Typically, the input file of our batch job is found from the file system. This means that we can configure its location by creating a new FileSystemResource
object.
Additional Reading:
- Lesson: Streaming API for XML
- Spring Batch Reference Documentation: StaxEventItemReader
Before our ItemReader
bean can transform the student information read from the student.xml file into StudentDTO
objects, we have to configure the name of the fragment root element in the StudentDTO
class. We can do this by following these steps:
- Annotate the class with the
@XmlRootElement
annotation. - Configure the name of the root element by setting the value of the
@XmlRootElement
annotation’sname
attribute to: ‘student’.
After we have made this change to the StudentDTO
class, its source code looks as follows:
import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="student") public class StudentDTO { private String emailAddress; private String name; private String purchasedPackage; public StudentDTO() {} public String getEmailAddress() { return emailAddress; } public String getName() { return name; } public String getPurchasedPackage() { return purchasedPackage; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public void setName(String name) { this.name = name; } public void setPurchasedPackage(String purchasedPackage) { this.purchasedPackage = purchasedPackage; } }
StudentDTO
class, we don’t have to add additional annotations to the StudentDTO
class. If the element names aren’t the same as the field names of the target class, or we have to use custom marshalling, we have to annotate our DTO class with JAXB annotations.
Additional Reading:
- JAXB Users Guide: 3. Annotating Your Classes
We can now read the input data of our batch job from an XML file. Let’s summarize what we learned from this blog post.
Summary
This blog post has taught us five things:
- The
spring-oxm
dependency helps us to serialize objects to XML documents and deserialize XML documents to objects. - The
jaxb-api
dependency allows us to compile code which uses the JAXB API when we are using Java 11 or newer. - The
jaxb-runtime
dependency allows us to run an application which uses the JAXB API when we are using Java 11 or newer. - We can read the input data of our batch job from an XML file by using the
StaxEventItemReader
class. - We must configure the name of the fragment root element by annotating our DTO class with the
@XmlRootElement
annotation.
P.S. You can get the example application of this blog post from Github.





Related Stories
- Spring Batch Tutorial: Writing Information to a Database With JDBC
- Spring From the Trenches: Cleaning Up Our Test Code With HTTP Request Builders
- Spring From the Trenches: Disabling Cookie Management of Apache HTTP Client 4 and RestTemplate