I'm using Spring Batch 3.0.3 configured with annotation to create a batch job that repeats a step an undetermined number of times.
My first step will read into memory a list of items used during the repeating step. I'd like the repeating steps to iterate through this job-scoped list.
How can I configure my job to run the same step x times? I've seen examples in xml of a step specifying the next step to run. I'm thinking I could point two steps to each other in an infinite loop until the list has been iterated. Would this work and is there a way to do it with annotations? Below is my main configuration file with some code that wasn't working.
@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class))
@EnableAutoConfiguration
@EnableBatchProcessing
@Loggable
public class BatchCrudConfiguration
{
@Bean
public Job batchCRUDJob(JobBuilderFactory jobBuilderFactory, Step[] processSheetSteps)
{
JobBuilder jobBuilder = jobBuilderFactory.get("batchCRUDJob").incrementer(new RunIdIncrementer());
FlowBuilder<FlowJobBuilder> jobFlowBuilder = jobBuilder.flow(processSheetSteps[0]);
for (int i = 1; i < processSheetSteps.length; i++)
{
jobFlowBuilder = jobFlowBuilder.next(processSheetSteps[i]);
}
return jobFlowBuilder.end().build();
}
@Bean
public Step[] processSheetSteps(
StepBuilderFactory stepBuilderFactory,
RawDataReader[] readers,
DelegatingWriter writer,
DelegatingProcessor processor,
@Value("${batchcrud.chunkSize}") int chunkSize)
{
int numberOfReaders = readers.length;
Step[] steps = new Step[numberOfReaders];
for (int i = 0; i < numberOfReaders; i++)
{
steps[i] = stepBuilderFactory.get("processSheet" + i + "Step").<RawData, DataItem>
chunk(chunkSize).reader(readers[i]).processor(processor).writer(writer).build();
}
return steps;
}
The way I'd approach this is via the following:
StepExecutionListener
that evaluates if there are more items in the list to process. If so, it returns an ExitStatus
that maps to the same step. If not, it returns an ExitStatus
that maps to end the job or continue the job (based on the rest of the flow).For example:
StepExecutionListener
public class MyListener {
@Autowired
private List myItems;
@AfterStep
public ExitStatus afterStep(StepExecution stepExecution) {
if(myItems.size() > 0) {
return new ExitStatus("CONTINUE");
}
else {
return new ExitStatus("FINISHED");
}
}
}
Job Configuration
...
@Bean
public Step step1() {...}
@Bean
public MyListener listener() {..}
@Bean
public Step step2(MyListener listener) {
return stepBuilder.get("step2")
.tasklet(myTasklet()) // Replace this piece as needed
.listener(listener).build();
}
@Bean
public Job job1(Step step1, Step step2) {
return jobBuilder.get("job1")
.start(step1)
.next(step2).on("CONTINUE").to(step2).on("FINISHED").end()
.build();
}
...
Note I have not tested this code so there may be typos, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With