What is Spring Batch's JobLauncher, and how do you use it to start a job?
answer
- run(job, jobParameters) -> JobExecution
- params identify the JobInstance
- TaskExecutorJobLauncher is the impl
- needs a JobRepository
- inject to trigger on demand
basics
~10 sJobLauncher is the interface that starts a batch Job. You call jobLauncher.run(job, jobParameters). It returns a JobExecution describing that run (status, id, timestamps).
solid answer
~40 sJobLauncher is the entry point that starts a Job. Its one method, run(Job job, JobParameters jobParameters), executes the job and returns a JobExecution — a record of that single run with its BatchStatus, ExitStatus, id, and start/end times. JobParameters (key/value pairs) identify the JobInstance, so the same job with the same identifying parameters is the same logical instance; different parameters (e.g. a run date or a run.id) make a new instance. In Spring Boot you rarely wire it by hand: Boot auto-configures a TaskExecutorJobLauncher backed by a JobRepository, and JobLauncherApplicationRunner calls run() for you on startup. You inject JobLauncher when you want to trigger a job yourself — from a REST controller, a message listener, or a @Scheduled method.
code
java · 19 lines@RestController
class BatchController {
private final JobLauncher jobLauncher;
private final Job importJob;
BatchController(JobLauncher jobLauncher, Job importJob) {
this.jobLauncher = jobLauncher;
this.importJob = importJob;
}
@PostMapping("/import")
ResponseEntity<Long> trigger() throws Exception {
JobParameters params = new JobParametersBuilder()
.addLong("run.id", System.currentTimeMillis())
.toJobParameters();
JobExecution exec = jobLauncher.run(importJob, params);
return ResponseEntity.ok(exec.getId());
}
}go deeper
Know the signature run(job, params) -> JobExecution and that you inject JobLauncher to start a job.
Explain JobInstance vs JobExecution and that identifying parameters drive instance identity.
Discuss where the launcher comes from (Boot auto-config, TaskExecutorJobLauncher), the JobRepository dependency, and re-run semantics.
Frame JobLauncher as the trigger boundary; contrast on-startup vs on-demand triggering and metadata persistence guarantees.
## What JobLauncher is `JobLauncher` is a Spring Batch interface (package `org.springframework.batch.core.launch`) with a single method: ```java JobExecution run(Job job, JobParameters jobParameters) throws ...; ``` It is the **boundary between 'I have a Job bean' and 'the job actually runs.'** A `Job` is just a definition (steps, flow); nothing happens until a `JobLauncher` executes it. ## Key domain objects - **Job** — the definition (one or more `Step`s and their flow). - **JobParameters** — an immutable set of typed key/value pairs (String, Long, Double, Date/LocalDate). They serve two purposes: (1) pass runtime input into the job, and (2) **identify** the run. By default every parameter is *identifying*, meaning it contributes to the identity of the `JobInstance`. - **JobInstance** — the logical 'job + identifying parameters' combination. Running the same job with parameters `{date=2026-07-22}` twice refers to the **same** JobInstance. - **JobExecution** — a single physical *attempt* to run a JobInstance. It carries the `BatchStatus` (STARTING, STARTED, COMPLETED, FAILED…), an `ExitStatus`, a numeric id, start/end times, and a list of `StepExecution`s. `run()` returns this object. ## How you call it ```java @Autowired JobLauncher jobLauncher; @Autowired Job importJob; JobParameters params = new JobParametersBuilder() .addLocalDate("runDate", LocalDate.now()) .addLong("run.id", System.currentTimeMillis()) .toJobParameters(); JobExecution execution = jobLauncher.run(importJob, params); System.out.println(execution.getStatus()); // e.g. COMPLETED ``` ## Where JobLauncher comes from You almost never implement it. Spring Boot's batch auto-configuration provides a bean of type `JobLauncher` — concretely a **`TaskExecutorJobLauncher`** (renamed from `SimpleJobLauncher` in Spring Batch 5). That launcher needs a **`JobRepository`** (the persistence store for batch metadata) because before it runs the job it *persists* the new JobExecution row so the run is recorded and restartable. ## When you inject it yourself Boot auto-runs jobs on startup via `JobLauncherApplicationRunner`. But if you want to trigger a job **on demand** — from a REST endpoint, a Kafka/JMS listener, or a `@Scheduled` method — you inject `JobLauncher` and call `run()` with freshly built `JobParameters`. ## Common gotchas - **Re-running with identical identifying parameters** that already COMPLETED throws `JobInstanceAlreadyCompleteException`. Add a unique parameter (a timestamp / `run.id`) to force a new instance, or use `RunIdIncrementer`. - `JobParameters` must be built with `JobParametersBuilder`; they are immutable. - `run()` is **blocking by default** — it returns only after the job finishes (see the sync-vs-async question).
- What does run() return and what is inside it?A JobExecution: the run's id, BatchStatus, ExitStatus, start/end times, and the StepExecutions. It represents one physical attempt at a JobInstance.
- Why add a timestamp or run.id parameter?Identifying parameters define the JobInstance. Reusing the same set after a COMPLETED run throws JobInstanceAlreadyCompleteException, so a unique value forces a fresh instance.
saying these in an interview costs you the question
- Thinking JobLauncher defines the job's steps (that's the Job).
- Believing run() returns void or just a status string.
- Not knowing JobParameters identify the instance.