skip to content

JobLauncher

JobLauncher runs a job with parameters, synchronously by default, and Boot can launch jobs automatically at startup. Interviewers ask whether a batch job should run inside a web app at all, and how you would trigger it instead.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

5

What is Spring Batch's JobLauncher, and how do you use it to start a job?

level: juniorimportance: must knowfreq 70%

answer

  1. run(job, jobParameters) -> JobExecution
  2. params identify the JobInstance
  3. TaskExecutorJobLauncher is the impl
  4. needs a JobRepository
  5. inject to trigger on demand

basics

~10 s

JobLauncher 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 s

JobLauncher 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
java
@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

for a junior

Know the signature run(job, params) -> JobExecution and that you inject JobLauncher to start a job.

for a middle

Explain JobInstance vs JobExecution and that identifying parameters drive instance identity.

for a senior

Discuss where the launcher comes from (Boot auto-config, TaskExecutorJobLauncher), the JobRepository dependency, and re-run semantics.

for a principal

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.

context

open as a page

By default is jobLauncher.run() blocking or non-blocking, and how do you make it asynchronous?

level: middleimportance: must knowfreq 68%

basics

~20 s

By default run() is blocking: TaskExecutorJobLauncher uses a SyncTaskExecutor, so it runs the job in the caller thread and returns only when it finishes. Give the launcher an async TaskExecutor to make run() return immediately.

open as a page

How does Spring Boot automatically run batch jobs on startup, and how do you control which jobs run?

level: middleimportance: should knowfreq 55%

basics

~10 s

Boot registers a JobLauncherApplicationRunner that, after the context starts, calls JobLauncher.run() on the Job beans it finds. It's on by default; set spring.batch.job.enabled=false to disable, or spring.batch.job.name to pick a specific job.

open as a page

What checked exceptions can JobLauncher.run() throw, and what do they tell you about job identity and restart?

level: seniorimportance: should knowfreq 45%

basics

~10 s

run() throws four checked exceptions: JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, and JobParametersInvalidException. They signal that the run couldn't even start because of the job's identity, state, or bad parameters.

open as a page

You must trigger a long-running batch job from a REST endpoint. Design the launching mechanism and justify the trade-offs.

level: principalimportance: should knowfreq 35%

basics

~20 s

Don't use the default blocking launcher on an HTTP thread. Configure a TaskExecutorJobLauncher with a bounded ThreadPoolTaskExecutor so run() returns immediately with an execution id; the client polls a status endpoint that reads the JobRepository.

open as a page