JobExecutionListener in Spring Batch (Complete Guide with beforeJob & afterJob)

If you are working with Spring Batch, one of the most powerful features you can use is the JobExecutionListener. This listener allows you to run custom logic before and after a batch job executes, making it ideal for logging, validation, auditing, notifications, performance tracking, and more.

This in-depth guide explains:

  • ✔ What JobExecutionListener is
  • ✔ Real-world use cases
  • ✔ Complete Spring Boot example
  • ✔ How to pass data between beforeJob() and afterJob()
  • ✔ Best practices for production-ready batch jobs

What Is JobExecutionListener in Spring Batch?

JobExecutionListener is a callback interface in Spring Batch that allows you to intercept job lifecycle events. Spring Batch automatically invokes two methods:

  • beforeJob() → before the job begins
  • afterJob() → after the job completes (success or failure)

public interface JobExecutionListener {
    void beforeJob(JobExecution jobExecution);
    void afterJob(JobExecution jobExecution);
}

Why Should You Use It? (Real Use Cases)

  • Logging & monitoring job start/end times
  • Initializing or cleaning up resources
  • Validating job prerequisites
  • Passing shared data using ExecutionContext
  • Sending notifications after job completion
  • Auditing and writing analytics

Setting Up Spring Batch with JobExecutionListener

1. Add Spring Batch Dependency


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>

2. Create the Job Listener

This listener logs start/end times and uses ExecutionContext to store metadata.


@Component
public class MyJobListener implements JobExecutionListener {

    @Override
    public void beforeJob(JobExecution jobExecution) {
        System.out.println(">>> Job is starting: " + jobExecution.getJobInstance().getJobName());

        jobExecution.getExecutionContext().putString(
                "startTime",
                LocalDateTime.now().toString()
        );
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        System.out.println(">>> Job finished with status: " + jobExecution.getStatus());

        String startTime = jobExecution.getExecutionContext().getString("startTime");
        LocalDateTime endTime = LocalDateTime.now();

        System.out.println(">>> Started at: " + startTime);
        System.out.println(">>> Ended at: " + endTime);
    }
}

3. Configure the Job & Step


@Configuration
public class SpringBatchConfig {

    @Autowired
    private MyJobListener myJobListener;

    @Autowired
    private JobRepository repository;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Bean
    public Job sampleJob() {
        return new JobBuilder("sample-job", repository)
                .incrementer(new RunIdIncrementer())
                .listener(myJobListener)
                .start(sampleStep())
                .build();
    }

    @Bean
    public Step sampleStep() {
        return new StepBuilder("sample-step", repository)
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("Executing step logic...");
                    return RepeatStatus.FINISHED;
                }, platformTransactionManager)
                .build();
    }
}

Expected Output


>>> Job is starting: sample-job
>>> Executing step logic...
>>> Job finished with status: COMPLETED
>>> Started at: 2025-04-21T14:30:12
>>> Ended at: 2025-04-21T14:30:14

Best Practices & Pro Tips

  • Inject services like email, logging, or database repositories inside your listener.
  • Use ExecutionContext to pass values between before/after job or across steps.
  • Track job duration & performance metrics for dashboards (Grafana, Kibana, etc.).
  • Send alerts in afterJob() if jobExecution.getStatus() == BatchStatus.FAILED.
  • Use multiple listeners if needed—Spring Batch supports chaining.

Frequently Asked Questions

1. Can I have more than one JobExecutionListener?
Yes, Spring Batch allows multiple listeners attached to the same job.

2. How is JobExecutionListener different from StepExecutionListener?
JobExecutionListener runs once per job, while StepExecutionListener runs for every step.

3. Can a listener stop a job from running?
Yes, by throwing an exception inside beforeJob().

Conclusion

JobExecutionListener is an essential extension point in Spring Batch that helps you hook into job lifecycle events. Whether you need monitoring, analytics, validation, or notifications, these lifecycle callbacks make your batch jobs more robust and reliable.