I am working on a Spring Batch application and I have the following problem.
I have the definition of a single step Job containing this step:
@Bean
public Step readNotaryListStep(){
return steps.get("readNotaryListStep").
<Integer,Integer>chunk(1)
.reader(serviceItemReader())
.processor(new NotaryDetailsEnrichProcessor(notaryService))
.writer(new NotaryWriter(wpService))
.build();
}
@Bean(name="updateNotaryListInfoJob")
public Job updateNotaryListInfoJob(){
return jobs.get("updateNotaryListInfoJob")
.incrementer(new RunIdIncrementer())
.start(readNotaryListStep())
.build();
}
It works fine. Basically it is reading from a reader, the output is processed and finnally it is written by the new NotaryWriter(wpService) that I create for the writer.
Ok...the following need has now emerged: after that the Job complete I need to call a method called resetCounter() defined into my NotaryWriter class (the class set for the writer section of my step).
Is it possible to implement a behavior like this? In case how can I implement it?
CodePudding user response:
You can implement a JobExecutionListener
or even StepExecutionListener
which allow you to add a callback when a job and a step is completed. Both of them can be configured by the listener()
on the JobBuilder
and StepBuilder
.
To allow the JobExecutionListener
to call a method on the same instance of NotaryWriter
that is configured in the step , you have to make NotaryWriter
as a spring bean rather than create it manually , and make sure both the JobExecutionListener
and the step refer to it.
Something likes :
@Bean
public NotaryWriter notaryWriter(){
return new NotaryWriter(wpService);
}
And inject it into both JobExecutionListener
and the Step
:
@Component
public MyJobExecutionListener implements JobExecutionListener {
@Autowired
private NotaryWriter notaryWriter;
public void beforeJob(JobExecution jobExecution){
}
public void afterJob(JobExecution jobExecution){
notaryWriter.resetCounter();
}
}
@Bean
public Step readNotaryListStep(NotaryWriter notaryWriter){
return steps.get("readNotaryListStep").
.........
.writer(notaryWriter)
.build();
}
I just show you the general idea . You have to consider the scope of the JobExecutionListener
and the NotaryWriter
based on the things you want to do. It supports job scope , step scope or just application scope out of the box.
Because it seems to me that you actually want each step has their own instance of NotaryWriter
such that its counter will not mess up with each other. If yes , you could simply define it as the @StepScope
and do not need any listener :
@Bean
@StepScope
public NotaryWriter notaryWriter(){
return new NotaryWriter(wpService);
}
@Bean
public Step readNotaryListStep(NotaryWriter notaryWriter){
return steps.get("readNotaryListStep").
.........
.writer(notaryWriter)
.build();
}