Skip to main content
Advertisement

15.3 Deep Dive: ItemReader, ItemProcessor, ItemWriter

1. FlatFileItemReader — CSV File Processing

@Bean
public FlatFileItemReader<MemberCsvDto> csvMemberReader() {
return new FlatFileItemReaderBuilder<MemberCsvDto>()
.name("csvMemberReader")
.resource(new ClassPathResource("data/members.csv"))
.delimited()
.names("name", "email", "age") // Map CSV columns to field names
.targetType(MemberCsvDto.class)
.linesToSkip(1) // Skip header row
.build();
}

2. ItemProcessor — Transformation and Filtering

ItemProcessor transforms each item from input to output type. Returning null filters out that item — it won't be passed to the Writer.

@Bean
public ItemProcessor<MemberCsvDto, Member> memberCsvToEntityProcessor() {
return csvDto -> {
// Filter out minors
if (csvDto.getAge() < 18) {
return null; // null = filtered out, not passed to writer
}
return Member.builder()
.name(csvDto.getName())
.email(csvDto.getEmail())
.age(csvDto.getAge())
.build();
};
}

3. CompositeItemProcessor — Chaining Processors

Use this when you want to chain multiple transformation/validation steps in order.

@Bean
public CompositeItemProcessor<MemberCsvDto, Member> compositeProcessor() {
CompositeItemProcessor<MemberCsvDto, Member> processor = new CompositeItemProcessor<>();
processor.setDelegates(List.of(
new AgeFilterProcessor(), // Step 1: Age filter
new EmailValidateProcessor(), // Step 2: Email format validation
new CsvToEntityProcessor() // Step 3: Final entity transformation
));
return processor;
}

4. ItemWriteListener — Post-Write Success/Failure Handling

@Component
public class BatchWriteListener implements ItemWriteListener<Member> {

@Override
public void afterWrite(Chunk<? extends Member> items) {
log.info("Successfully saved {} items", items.size());
}

@Override
public void onWriteError(Exception exception, Chunk<? extends Member> items) {
log.error("Write failed! Failed items: {}", items);
// Send Slack alert or push to a Dead Letter Queue
}
}
Advertisement