skip to content

ExecutionContext

The ExecutionContext is a persisted key-value map at job and step scope where a reader stores its position so a restart can resume. Interviewers ask how a failed job picks up where it left off, and this is the mechanism.

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

explore

questions

5

What is the ExecutionContext in Spring Batch, and what is it used for?

level: juniorimportance: must knowfreq 70%

answer

  1. key/value map persisted in JobRepository
  2. step-scoped + job-scoped, not shared
  3. putLong/getString typed accessors
  4. survives restart -> readers resume
  5. small state only

basics

~20 s

ExecutionContext is a persisted key/value map Spring Batch attaches to a running job or step. It stores state — like how many items were read — so if the job stops and restarts, it can pick up where it left off.

solid answer

~40 s

The ExecutionContext is a serializable String-keyed map that Spring Batch persists in the JobRepository. Every StepExecution has its own step-scoped context and every JobExecution has a job-scoped context. Framework components and your code stash small pieces of state in it — item-read counts, file cursor positions, running totals. Because it is written to the database at chunk-commit boundaries, it survives a crash: when you restart a failed job the same context is reloaded, so a reader can skip already-processed items instead of starting over. You read/write it with typed accessors like putLong, putString, put and getLong/getString. It is meant for small state, not for passing large data between steps.

code

java · 11 lines
java
public class CountingTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
        ExecutionContext ctx = chunkContext.getStepContext()
                .getStepExecution().getExecutionContext();
        long processed = ctx.getLong("processed", 0L); // second arg = default
        processed += doWork();
        ctx.putLong("processed", processed); // marks context dirty; persisted at commit
        return RepeatStatus.FINISHED;
    }
}

go deeper

for a junior

Should know it is a persisted key/value store used for resuming.

for a middle

Should distinguish step vs job scope and know it lives in the JobRepository DB.

for a senior

Should tie persistence timing (chunk commit) to restart semantics.

for a principal

Should reason about serialization, size limits, and it as a design boundary (not a data bus).

## What it is The `ExecutionContext` (`org.springframework.batch.item.ExecutionContext`) is a **persisted, serializable key/value map** — essentially a `Map<String, Object>` with typed accessors — that Spring Batch uses to carry state across the lifecycle of a batch execution, including across JVM restarts. ## Two scopes There are **two distinct contexts**, and they are not automatically shared: - **Step ExecutionContext** — one per `StepExecution`. Scoped to a single step run. This is where readers store their progress. - **Job ExecutionContext** — one per `JobExecution`. Scoped to the whole job run, useful for sharing a value across steps (with promotion — see the listener question). You obtain them from the `StepExecution`/`JobExecution` objects: `stepExecution.getExecutionContext()` and `stepExecution.getJobExecution().getExecutionContext()`. ## Typed accessors Instead of casting, you use `putLong`, `putInt`, `putDouble`, `putString`, and generic `put(key, obj)`, plus `getLong`, `getString`, `get`, `containsKey`. There is also a `dirty` flag: mutations mark the context dirty so the framework knows it must be re-persisted. ## Where it lives The `JobRepository` serializes the context into database tables — `BATCH_STEP_EXECUTION_CONTEXT` and `BATCH_JOB_EXECUTION_CONTEXT` (columns like `SHORT_CONTEXT` and `SERIALIZED_CONTEXT`). Serialization is handled by an `ExecutionContextSerializer` (Jackson-based by default in modern Spring Batch). ## Why it matters — restartability The step context is persisted **at each chunk commit**. So after processing chunk N, the count/cursor is durable. If the JVM dies mid-job, restarting the same `JobInstance` reloads the saved context and stateful readers (`FlatFileItemReader`, `JdbcCursorItemReader`, etc.) resume from where they stopped rather than reprocessing everything. ## Gotchas - Keep it **small** — the DB columns are size-limited; don't stuff large objects or collections. - Values must be **serializable** by the configured serializer. - Step and job contexts are **separate** — writing to the step context does not make a value visible to later steps. ## When to use Use it for small resumable state and cross-step signals. Do **not** use it as a general data bus for large payloads — that is what item readers/writers and staging tables are for.

  • Where is the ExecutionContext actually stored?
    In the JobRepository — serialized into the BATCH_STEP_EXECUTION_CONTEXT and BATCH_JOB_EXECUTION_CONTEXT tables, via an ExecutionContextSerializer (Jackson-based by default).
  • If I put a value in the step context, can the next step read it?
    No. Step and job contexts are separate. You must promote the key to the job context (e.g. with ExecutionContextPromotionListener) for a later step to see it.

saying these in an interview costs you the question

  • Thinking there is one shared context for the whole job
  • Believing it lives only in memory and is lost on restart
  • Using it to pass large datasets between steps

context

open as a page

Explain the difference between the step-scoped and job-scoped ExecutionContext, and when each is persisted.

level: middleimportance: must knowfreq 60%

basics

~20 s

Each StepExecution has its own step context; each JobExecution has a job context. They are separate. The step context is saved to the database at every chunk commit; the job context is saved as the job execution is updated.

open as a page

What is ExecutionContextPromotionListener and how do you use it to share data between steps?

level: seniorimportance: should knowfreq 45%

basics

~20 s

It's a step listener that copies chosen keys from a step's ExecutionContext up to the job's ExecutionContext after the step finishes. That's how a value produced in one step becomes readable by a later step.

open as a page

How does the ExecutionContext enable a reader to resume mid-step after a failure? Walk through the ItemStream mechanics.

level: seniorimportance: should knowfreq 50%

basics

~20 s

Stateful readers implement ItemStream. On open() they read a saved position from the ExecutionContext; on update() (called per chunk) they write the current read count. After a crash, restart calls open() with the saved context so the reader skips already-read items.

open as a page

What are the serialization, sizing, and consistency pitfalls of the ExecutionContext, and how do they influence how you use it?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

The context is serialized into size-limited DB columns, so keep it small and serializable. It's saved per chunk with the transaction, so it stays consistent with the data. Don't store large objects or non-serializable types, and namespace keys to avoid collisions.

open as a page