-
Notifications
You must be signed in to change notification settings - Fork 0
feat(spring-batch-file-example): implement Spring Batch file processi… #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| package com.io.example.config; | ||
|
|
||
| import com.io.example.dto.StudentDto; | ||
| import com.io.example.reader.StreamingExcelItemReader; | ||
| import com.io.example.service.StudentService; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.batch.core.Step; | ||
| import org.springframework.batch.core.configuration.annotation.StepScope; | ||
| import org.springframework.batch.core.repository.JobRepository; | ||
| import org.springframework.batch.core.step.builder.StepBuilder; | ||
| import org.springframework.batch.item.ItemProcessor; | ||
| import org.springframework.batch.item.ItemWriter; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.core.io.ClassPathResource; | ||
| import org.springframework.transaction.PlatformTransactionManager; | ||
|
|
||
| import java.time.LocalDate; | ||
|
|
||
| @Configuration | ||
| @RequiredArgsConstructor | ||
| public class LargeExcelReadBatchConfig { | ||
|
|
||
| private final StudentService studentService; | ||
|
|
||
| @Bean | ||
| @StepScope | ||
| public StreamingExcelItemReader<StudentDto> largeExcelReader( | ||
| @Value("#{jobParameters['filePath']}") String filePath | ||
| ) { | ||
| return new StreamingExcelItemReader<>( | ||
| new ClassPathResource(filePath), | ||
| row -> new StudentDto( | ||
| row.getCell(0).getStringCellValue(), | ||
| row.getCell(1).getStringCellValue(), | ||
| LocalDate.parse(row.getCell(2).getStringCellValue()) | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| @Bean | ||
| public ItemProcessor<StudentDto, StudentDto> largeExcelProcessor() { | ||
| return student -> student; | ||
| } | ||
|
|
||
| @Bean | ||
| public ItemWriter<StudentDto> largeExcelWriter() { | ||
| return items -> items.forEach(studentService::print); | ||
| } | ||
|
|
||
| @Bean | ||
| public Step largeExcelStep( | ||
| JobRepository jobRepository, | ||
| PlatformTransactionManager transactionManager, | ||
| StreamingExcelItemReader<StudentDto> largeExcelReader, | ||
| ItemProcessor<StudentDto, StudentDto> largeExcelProcessor, | ||
| ItemWriter<StudentDto> largeExcelWriter, | ||
| @Value("${spring.batch.chunk-size}") int chunkSize | ||
| ) { | ||
| return new StepBuilder("largeExcelStep", jobRepository) | ||
| .<StudentDto, StudentDto>chunk(chunkSize, transactionManager) | ||
| .reader(largeExcelReader) | ||
| .processor(largeExcelProcessor) | ||
| .writer(largeExcelWriter) | ||
| .build(); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package com.io.example.config; | ||
|
|
||
| import com.io.example.dto.StudentDto; | ||
| import com.io.example.mapper.StudentMapper; | ||
| import com.io.example.service.StudentService; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.batch.core.Step; | ||
| import org.springframework.batch.core.configuration.annotation.StepScope; | ||
| import org.springframework.batch.core.repository.JobRepository; | ||
| import org.springframework.batch.core.step.builder.StepBuilder; | ||
| import org.springframework.batch.extensions.excel.poi.PoiItemReader; | ||
| import org.springframework.batch.item.ItemProcessor; | ||
| import org.springframework.batch.item.ItemWriter; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.core.io.ClassPathResource; | ||
| import org.springframework.transaction.PlatformTransactionManager; | ||
|
|
||
| @Configuration | ||
| @RequiredArgsConstructor | ||
| public class SmallExcelReadBatchConfig { | ||
|
|
||
| private final StudentService studentService; | ||
|
|
||
| @Bean | ||
| @StepScope | ||
| public PoiItemReader<StudentDto> smallExcelReader( | ||
| @Value("#{jobParameters['filePath']}") String filePath | ||
| ) { | ||
| PoiItemReader<StudentDto> reader = new PoiItemReader<>(); | ||
| reader.setResource(new ClassPathResource(filePath)); | ||
| reader.setLinesToSkip(1); | ||
| reader.setRowMapper(new StudentMapper()); | ||
| return reader; | ||
| } | ||
|
|
||
| @Bean | ||
| public ItemProcessor<StudentDto, StudentDto> smallExcelProcessor() { | ||
| return student -> student; | ||
| } | ||
|
Comment on lines
+38
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Consider removing the identity processor. The processor returns the input unchanged ( ♻️ Simplification optionIf no processing is required, remove the processor bean and update the step configuration: - @Bean
- public ItemProcessor<StudentDto, StudentDto> smallExcelProcessor() {
- return student -> student;
- }
-
@Bean
public Step smallExcelStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
PoiItemReader<StudentDto> smallExcelReader,
- ItemProcessor<StudentDto, StudentDto> smallExcelProcessor,
ItemWriter<StudentDto> smallExcelWriter,
@Value("${spring.batch.chunk-size}") int chunkSize) {
return new StepBuilder("smallExcelStep", jobRepository)
.<StudentDto, StudentDto>chunk(chunkSize, transactionManager)
.reader(smallExcelReader)
- .processor(smallExcelProcessor)
.writer(smallExcelWriter)
.build();
}Note: Apply the same simplification to
🤖 Prompt for AI Agents |
||
|
|
||
| @Bean | ||
| public ItemWriter<StudentDto> smallExcelWriter() { | ||
| return items -> items.forEach(studentService::print); | ||
| } | ||
|
|
||
| @Bean | ||
| public Step smallExcelStep(JobRepository jobRepository, | ||
| PlatformTransactionManager transactionManager, | ||
| PoiItemReader<StudentDto> smallExcelReader, | ||
| ItemProcessor<StudentDto, StudentDto> smallExcelProcessor, | ||
| ItemWriter<StudentDto> smallExcelWriter, | ||
| @Value("${spring.batch.chunk-size}") int chunkSize) { | ||
|
|
||
| return new StepBuilder("smallExcelStep", jobRepository) | ||
| .<StudentDto, StudentDto>chunk(chunkSize, transactionManager) | ||
| .reader(smallExcelReader) | ||
| .processor(smallExcelProcessor) | ||
| .writer(smallExcelWriter) | ||
| .build(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add defensive checks for cell values and date parsing.
The inline row mapper is fragile:
getStringCellValue()will throw if a cell is null or not a string typeLocalDate.parse()assumes ISO-8601 format and will throwDateTimeParseExceptionon invalid inputThe
SmallExcelReadBatchConfiguses a dedicatedStudentMapperclass, which likely handles these edge cases. Consider reusing that mapper or adding similar defensive logic here.Proposed defensive implementation
Based on learnings, this is a demonstration project, so minimal error handling may be acceptable if intentional.
📝 Committable suggestion
🤖 Prompt for AI Agents