Custom FieldSetMapper example

In the previous post “Spring Batch Simple Example” we used “BeanWrapperFieldSetMapper” while reading the employee records from the file. The BeanWrapperFieldSetMapper created a new
instance of Employee class for every employee record in the file and set the instance fields.

We can more have control on the task performed by BeanWrapperFieldSetMapper by providing a custom implementation of FieldSetMapper interface.

This post explains the above point with an example

First we need to create a class which implements FieldSetMapper and provide implementation for the interface method “mapFieldSet” as shown below

Custom implementation of FieldSetMapper


package package2;

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

public class EmployeeFieldSetMapper implements FieldSetMapper {
    @Override
    public Employee mapFieldSet(FieldSet fieldSet) throws BindException {
        Employee employee = new Employee();
        employee.setId(fieldSet.readString("id"));
        employee.setName(fieldSet.readString("name"));
        employee.setStatus(fieldSet.readString("status"));
        employee.setSalary(fieldSet.readBigDecimal("salary"));
        return employee;
    }
}

In the above code, fieldSet parameter created by LineTokenizer implementation is passed to mapFieldSet method. In the method we create an uninitialized instance of employee class
and then set its fields by retrieving the values from fieldSet. The FieldSet class has read methods one for each java primitive type. We pass field name or field index as parameter
to FieldSet’s read method.

Below is xml configuration of reader bean


1   <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
2       <property name="resource" value="file:FileInput.txt"/>
3       <property name="lineMapper">
4           <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
5               <property name="lineTokenizer">
6                   <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
7                       <property name="names" value="id,name,status,salary"/>
8                   </bean>
9               </property>
10              <property name="fieldSetMapper">
11                  <bean class="package2.EmployeeFieldSetMapper"/>
12              </property>
13          </bean>
14      </property> 
15  </bean>

In the above xml configuration, from line 10 to 12, we set the fieldSetMapper property of DefaultLineMapper to our custom implementation of FieldSetMapper.

Below is the complete xml configuration for your reference


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:batch="http://www.springframework.org/schema/batch"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">
    
    <bean id="employee" class="package2.Employee" scope="prototype"/>
    
    <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="package2.EmployeeFieldSetMapper"/>
                </property>
            </bean>
        </property> 
    </bean>
    
    <bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
        <property name="resource" value="file:DemoData2.txt"/>
        <property name="lineAggregator">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
                <property name="fieldExtractor">
                    <bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                        <property name="names" value="id,name,status,salary"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    
    <batch:job id="importEmployees">
        <batch:step id="readWriteEmployees">
            <batch:tasklet>
                <batch:chunk reader="reader" writer="writer" commit-interval="50"/>
            </batch:tasklet>
        </batch:step>
    </batch:job>
    
    <bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
    
    <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
    
    <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository"/>
    </bean>
</beans>
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s