In spring
batch, if the user wants to decide a Delimiter at run time based on the certain
criteria. Built-in spring batch Tokenizer classes won’t support this feature.
If we use our own customized class instead of using spring provided Tokenizer
class, spring batch throws an error.
Actual Configuration:
<bean
  id="defaultTokenizer"
  class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"> 
            <property
  name="delimiter" value="," /> 
</bean> 
<bean
  id="fieldSetMapper"
  class="com.mapper.CustomDataUploadFieldSetMapper" /> 
<bean
  id="defaultLineMapper"
  class="org.springframework.batch.item.file.mapping.DefaultLineMapper"> 
            <property
  name="lineTokenizer"
  ref="defaultTokenizer"></property> 
            <property
  name="fieldSetMapper"
  ref="fieldSetMapper"></property> 
</bean> 
<bean
  id="customDataItemReader"
  class="com.reader.CustomDataLoadReader"
  scope="prototype"> 
            <property
  name="lineMapper"
  ref="defaultLineMapper"></property> 
</bean> 
 | 
 
Here, if
we provide overridden Tokenizer instead of DelimitedLineTokenizer,
spring container will throw an error while server starts up.
We can
overcome this limitation by using anonymous inner bean configuration as
follows.
<bean
  id="customDataItemReader"
  class="com.reader.customerDataItemReader"
  scope="prototype"> 
      <property name="lineMapper"> 
            <bean
  class="com.mapper.CustomLineMapper"> 
                    <property
  name="lineTokenizer"> 
                        <bean
  class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer"> 
                                 <property
  name="delimiter" value="," /> 
                        </bean> 
                    </property> 
                    <property
  name="fieldSetMapper"> 
                        <bean
  class="com.mapper.SegmentFieldSetMapper" /> 
                    </property> 
            </bean> 
       </property> 
</bean> 
 | 
 
Write a CustomLineMapper by extending DefaultLineMapper and
override 
mapLine(String
line, int lineNumber) throws Exception method according
to requirements.
Example: Now
we need use pipe(|) symbol as delimiter if existed in the line, else need
to use comma(,) as default delimiter.
public class CustomLineMapper<T> extends DefaultLineMapper<T>
  { 
    private LineTokenizer lineTokenizer; 
    private FieldSetMapper<CustomerInformationVO>
  fieldSetMapper; 
    public <T> mapLine(String line, int
  lineNumber) throws Exception { 
       try { 
           setLineTokenizer(new DelimitedLineTokenizer(StringUtils.contains( 
                  line, '|') ? '|' : ',')); 
           return this.fieldSetMapper.mapFieldSet(this.lineTokenizer 
                 
  .tokenize(line)); 
       } catch (Exception ex) { 
           throw new FlatFileParseException("Parsing error at line: " 
                  +
  lineNumber + ", input=[" + line + "]", ex, line, 
                 
  lineNumber); 
       } 
    } 
    public LineTokenizer getLineTokenizer() { 
       return lineTokenizer; 
    } 
    public void setLineTokenizer(LineTokenizer lineTokenizer) { 
       this.lineTokenizer = lineTokenizer; 
    } 
    public void afterPropertiesSet() { 
       Assert.notNull(this.lineTokenizer, "The
  LineTokenizer must be set"); 
       Assert.notNull(this.fieldSetMapper, "The
  FieldSetMapper must be set"); 
    } 
    public FieldSetMapper<CustomerInformationVO>
  getFieldSetMapper() { 
       return fieldSetMapper; 
    } 
    public void setFieldSetMapper( 
           FieldSetMapper<CustomerInformationVO>
  fieldSetMapper) { 
       this.fieldSetMapper = fieldSetMapper; 
    } 
} 
 | 
 
No comments:
Post a Comment