Spring Batch Simple Example Part 1

In this post and next post, I will introduce Spring Batch to you with a simple example.

Spring batch is an open source framework useful for exporting data from source to destination in batches. The framework is very useful for batch applications.

Reading data

In our example, we will read employee records and move them to another file in batches. The fields of each employee record are separated by comma and each record is separated by a new line. For example below is the few lines from the file

EMP_ID0,EMP_NAME0,EMP_STATUS0,0
EMP_ID1,EMP_NAME1,EMP_STATUS1,1
EMP_ID2,EMP_NAME2,EMP_STATUS2,2
EMP_ID3,EMP_NAME3,EMP_STATUS3,3

To read from a file we need an instance of class org.springframework.batch.item.file.FlatFileItemReader. This class requires two information to do its job, they are
1) file name from which it has to read the records.
2) LineMapper instance which converts record at each line to appropriate objects.

Below is the bean definition of FlatFileItemReader


<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="resource" value="file:FileInput.txt"/>
        <property name="lineMapper">
            ...
        </property> 
    </bean>

For LineMapper to do its job, requires two information
1) an implementation of LineTokenizer interface which will extract fields from each record
2) an implementation of FieldSetMapper interface which will take fields extracted in step 1 and set it to appropriate object’ properties.

Below is the bean definition of LineMapper


<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
        <property name="resource" value="file:FileInput.txt"/>
        <property name="lineMapper">
            <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
                <property name="lineTokenizer">
                    <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                        <property name="names" value="id,name,status,salary"/>
                    </bean>
                </property>
                <property name="fieldSetMapper">
                    <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
                        <property name="prototypeBeanName" value="employee"/>
                    </bean>
                </property>
            </bean>
        </property> 
    </bean>

As shown in the above code, we create an instance of DefaultLineMapper, which takes an instance of DelimitedLineTokenizer and BeanWrapperFieldSetMapper.

DelimitedLineTokenizer extracts fields from each record. The instance assumes by default that each field in the record is separated by comma. Using comma as delimiter it extracts the fields. An instance of DelimitedLineTokenizer takes list of names, each name is associated to each field read, so that we can query the field’s value by name.

Next an instance of BeanWrapperFieldSetMapper class is given to DefaultLineMapper. This instance creates an employee object and set the object properties using the fields extracted.
The structure of the employee class is as shown below

Employee


package package1;

import java.math.BigDecimal;

public class Employee {
    private String id;
    private String name;
    private String status;
    private BigDecimal salary;
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getStatus() {
        return status;
    }
    public void setStatus(String status) {
        this.status = status;
    }
    public BigDecimal getSalary() {
        return salary;
    }
    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }
}

The property names of the employee class should match with the field names given to DelimitedLineTokenizer instance. A bean definition has to added for the employee class with prototype scope.

In next post, I will explain how to write the employee objects created in the reading process to a file.

Leave a Reply