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.


๐Ÿ‘‚ Related Spring Batch Monitoring & Execution Guides

Enhance your understanding of job execution monitoring by exploring related Spring Batch concepts such as error handling, retry strategies, conditional flows, and execution models.

๐Ÿงฑ Spring Batch Core Components

Understand how JobExecutionListener integrates with Job and Step lifecycles in Spring Batch.

๐Ÿšซ Skip Policy & Error Handling

Track skipped items, failures, and step outcomes using JobExecutionListener callbacks.

๐Ÿ” Retry Mechanism

Monitor retry attempts and retry exhaustion events during batch execution.

๐Ÿ”€ Conditional Flow in Jobs

Drive conditional job paths using execution status captured by listeners.

๐Ÿงต Multithreaded Step

Observe execution behavior and performance metrics in parallel batch processing scenarios.

๐Ÿ”„ ItemProcessor Example

Capture processing-level outcomes and validation failures using listeners.

⚙️ Spring Batch Tasklet

Track custom Tasklet execution status and implement monitoring hooks.