How can I call a method of the writer class when my Spring Batch Job complete?

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?

Answer

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();
}