In this post under Spring Batch, I will explain the purpose and how to use SuffixRecordSeparatorPolicy class with an example.
SuffixRecordSeparatorPolicy class is a concrete implementation of org.springframework.batch.item.file.separator.RecordSeparatorPolicy interface.
In one of my previous post I have explained the purpose of RecordSeparatorPolicy and how to use it.
For recap, RecordSeparatorPolicy interface is used to tell the reader what data represents a single record. The data can be in a single line or span multiple lines.
Its up to RecordSeparatorPolicy interface to decide what data makes up a record.
SuffixRecordSeparatorPolicy can be used with data that has a specific constant string as a suffix and indicates the end of record or act as delimiter between records. Note the record can span single or multiple lines. For example the below records have ” –END” as suffix and also act as delimiter between records.
EMP_ID0,EMP_FNAME0 EMP_LNAME0,
EMP_STATUS0,0 –END
EMP_ID1,EMP_FNAME1 EMP_LNAME1,
EMP_STATUS1,1 –END
EMP_ID2,EMP_FNAME2 EMP_LNAME2,
EMP_STATUS2,2 –END
EMP_ID3,EMP_FNAME3 EMP_LNAME3,
EMP_STATUS3,3 –END
EMP_ID4,EMP_FNAME4 EMP_LNAME4,
EMP_STATUS4,4 –END
EMP_ID5,EMP_FNAME5 EMP_LNAME5,
EMP_STATUS5,5 –END
EMP_ID6,EMP_FNAME6 EMP_LNAME6,
EMP_STATUS6,6 –END
In the above example, the data of each record span multiple line and end with ” –END”
Next I will show how to integrate an instance of SuffixRecordSeparatorPolicy to reader. Please refer to below xml code
1 <bean id="customRecordSeparatorPolicy" class="org.springframework.batch.item.file.separator.SuffixRecordSeparatorPolicy">
2 <property name="suffix" value=" --END"/>
3 </bean>
4
5 <bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
6 <property name="resource" value="file:FileInput4.txt"/>
7 <property name="recordSeparatorPolicy" ref="customRecordSeparatorPolicy"/>
8 <property name="lineMapper">
9 <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
10 <property name="lineTokenizer">
11 <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
12 <property name="names" value="id,name,status,salary"/>
13 </bean>
14 </property>
15 <property name="fieldSetMapper">
16 <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
17 <property name="prototypeBeanName" value="employee"/>
18 </bean>
19 </property>
20 </bean>
21 </property>
22 </bean>
In the above xml, at line 1 we create a bean definition for class SuffixRecordSeparatorPolicy and at line 7, we integrate the bean with reader bean by setting the recordSeparatorPolicy property. We indicate the string that is used as suffix or delimiter by setting the “suffix” property of SuffixRecordSeparatorPolicy class. In the above example the string ” –END” is set to suffix property of SuffixRecordSeparatorPolicy class.
Below is the complete xml 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="package21.Employee" scope="prototype"/>
<bean id="customRecordSeparatorPolicy" class="org.springframework.batch.item.file.separator.SuffixRecordSeparatorPolicy">
<property name="suffix" value=" --END"/>
</bean>
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="file:FileInput4.txt"/>
<property name="recordSeparatorPolicy" ref="customRecordSeparatorPolicy"/>
<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>
<bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:FileOutput.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" job-repository="jobRepository">
<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>