A step-scoped reader can receive job parameters when a step starts, so concurrent launches do not share an input path held by a singleton.
Spring Batch step scope: bind a reader to one execution
Bind at execution time
A settlement import receives its source path as a job parameter. The application context starts before any particular job execution exists, so a singleton reader cannot safely resolve that parameter at bean creation. Give the reader step scope and inject the parameter into its factory method. Spring creates the target when the step runs. The Step definition itself normally stays unscoped. Job identity explains why the source version must also be represented in the identifying parameters.
Keep paths and state separate
One reader instance belongs to one executing step. Do not store the current file name in a static field or mutate a shared bean before launching another job. A step-scoped proxy handles late access, but it does not make the underlying file immutable. Pin the file version before launch and verify it again on restart. Input snapshots and digest checks address that separate risk.
Test two launches
Launch two job instances with distinct source paths at the same time. Each should read only its own receipt references. Then fail one after a committed chunk and restart it with the same identifying input version; confirm its resumed reader still points at that source. A test that runs one job at a time cannot detect a shared mutable path.
Implementation contract
@Bean
@StepScope
FlatFileItemReader<ReceiptCsvRow> receiptReader(
@Value("#{jobParameters['inputPath']}") String inputPath,
LineMapper<ReceiptCsvRow> receiptLineMapper) {
return new FlatFileItemReaderBuilder<ReceiptCsvRow>()
.name("settlementReceiptReader")
.resource(new FileSystemResource(inputPath))
.lineMapper(receiptLineMapper)
.saveState(true)
.build();
}Cost and verification
The scoped proxy adds little per-item work because target creation happens at step start. File opening and replay dominate; the input must remain available for a restart.
Common Mistakes
- Do not step-scope the entire Step merely to inject a reader path.
- Do not reuse one mutable singleton reader across simultaneous executions.
- Do not equate a stable path string with immutable file contents.
Read next
Spring Batch job identity: a manifest ID defines restart versus a new run, Spring Batch restart input: pin the manifest before resuming a cursor, Spring Batch source digest: reject changed rows before a restart, Spring Batch FlatFileItemReader: save state against an immutable source, Spring Batch job scope: avoid a shared bean in partition workers.
