1

I need to get the line number into the FieldSet Mapper. How can I do this?

I want to use the lineNumber as a field of my resulting object produced by the Mapper.

<beans:bean id="fileReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
    <beans:property name="resource" 
        value="file:${batch.source}"/>
    <beans:property name="lineMapper">
        <beans:bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
            <beans:property name="lineTokenizer">
                <beans:bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                    <beans:property name="delimiter" value="${batch.delimiter}"/>
                    <beans:property name="names" value="${batch.columns}"/>
                </beans:bean>
            </beans:property>

            <beans:property name="fieldSetMapper">
                <beans:bean class="my.batch.mapper.ResourceFieldSetMapper"/>
            </beans:property>
        </beans:bean>
    </beans:property>
</beans:bean>

Thank You.

Armando
  • 310
  • 5
  • 18

2 Answers2

3

I realized that I can get the lineNumber value into MyObject by overriding the DefaultLineMapper with my own LineMapper in this way:

import org.springframework.batch.item.file.FlatFileParseException;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.transform.LineTokenizer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import my.model.MyObject;

public class MyLineMapper<T> implements LineMapper<MyObject>, InitializingBean {

    private LineTokenizer tokenizer;

    private ResourceFieldSetMapper fieldSetMapper;

    public MyObject mapLine(String line, int lineNumber) throws Exception {
        try{
            MyObject r = fieldSetMapper.mapFieldSet(tokenizer.tokenize(line));
            // this is the modification
            r.setLineNumber(lineNumber);
            return r;
        }
        catch(Exception ex){
            throw new FlatFileParseException("Parsing error at line: " + lineNumber + 
                    ", input=[" + line + "]", ex, line, lineNumber); 
        }
    }

    public void setLineTokenizer(LineTokenizer tokenizer) {
        this.tokenizer = tokenizer;
    }

    public void setFieldSetMapper(ResourceFieldSetMapper fieldSetMapper) {
        this.fieldSetMapper = fieldSetMapper;
    }

    public void afterPropertiesSet() {
        Assert.notNull(tokenizer, "The LineTokenizer must be set");
        Assert.notNull(fieldSetMapper, "The FieldSetMapper must be set");
    }

}

Thanks for your help! I hope this works for someone!

Blessings!

Armando
  • 310
  • 5
  • 18
1

I think you can use spEL expression #{fileReader.currentItemCount}, but there is the SB interface ItemCountAware for this purpose.

Marker interface indicating that an item should have the item count set on it. Typically used within an AbstractItemCountingItemStreamItemReader.

Luca Basso Ricci
  • 17,829
  • 2
  • 47
  • 69