0

I am trying to configure openCSV in the reader() step in the spring batch to directly convert a record read from a CSV file into a JAVA POJO. But I am running into the issue of how to correctly set the lineMapper with the openCSV.

As suggested in the post linked here How to replace flatFileItemReader with openCSV in spring batch, I am trying as below:

public Event reader() throws IOException {
        FlatFileItemReader<Event> itemReader = new FlatFileItemReader<Event>();
        itemReader.setLineMapper(lineMapper());
        itemReader.setLinesToSkip(1);
        itemReader.setResource(new FileSystemResource(inputFilePath));
        return itemReader;
    }

But I am not able to figure out how to configure the lineMapper:

    public LineMapper<Event> lineMapper() throws IOException {
       DefaultLineMapper<Event> lineMapper = new DefaultLineMapper<Event>();
       DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer("\t");
       BeanWrapperFieldSetMapper<Event> fieldSetMapper = new BeanWrapperFieldSetMapper<Event>();
       fieldSetMapper.setTargetType(Event.class);
       lineMapper.setLineTokenizer(???);
       lineMapper.setFieldSetMapper(???);

I have the code to read the file and convert it to the desired POJO but where to put it:

        try (
                Reader reader = Files.newBufferedReader(Paths.get(inputFilePath));
        ) {
            CsvToBean<Event> csvToBean = new CsvToBeanBuilder(reader)
                    .withSkipLines(1)
                    .withType(Event.class)
                    .withIgnoreLeadingWhiteSpace(true)
                    .build();
            return csvToBean.iterator().next();
        }

Any help to point me in the right direction is highly appreciated.

Abhinav
  • 43
  • 1
  • 5

1 Answers1

0

You are using the DefaultLineMapper and trying to set a LineTokenizer and FieldSetMapper in it, but this is not what is mentioned in the link you shared.

You need a custom implementation of the LineMapper interface that is based on OpenCSV:

public class OpenCSVLineMapper<T> implements LineMapper<T> {
    
    @Override
    public T mapLine(String line, int lineNumber) throws Exception {
        // TODO use OpenCSV to map a line to a POJO of type T
        return null;
    }
}

OpenCSV provides APIs to both read the file and map data to objects. You don't need the reading part as this will be done by the FlatFileItemReader from Spring Batch, you only need to use OpenCSV for the mapping part.

Once this in place, you can set your OpenCSV based line mapper implementation on the FlatFileItemReader:

public FlatFileItemReader<Event> reader() throws IOException {
   FlatFileItemReader<Event> itemReader = new FlatFileItemReader<Event>();
   itemReader.setResource(new FileSystemResource(inputFilePath));
   itemReader.setLinesToSkip(1);
   itemReader.setLineMapper(new OpenCSVLineMapper<>());
   return itemReader;
}
Mahmoud Ben Hassine
  • 28,519
  • 3
  • 32
  • 50
  • Firstly, thank you for guiding me ahead on this issue @mahmoud-ben-hassine. But what I am finding is, we use openCSV to map an input file directly to POJO via CsvToBean. So, I am not sure how to go about mapping a line to object T? – Abhinav Mar 18 '21 at 15:25
  • If I end up writing a code something like : `Event event = new Event(); event.setSomething(line[0]); event.setSomeOtherThing(line[1]); ..... ` then it brings the usefulness of openCSV in question as it was brought IN to avoid doing above in the first place. Because the above can be achieved without using openCSV. – Abhinav Mar 18 '21 at 15:35