Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Batch ExecutionContext keys: give each stream its own checkpoint

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

Readers and writers persist small restart values in an ExecutionContext; colliding keys can restore the wrong cursor or overwrite another component.

Treat the context as a shared map

A receipt reader stores its next offset and a writer stores its last output segment. Both may update the same StepExecution context at a checkpoint. Keys such as index or position are too vague; use stable, component-specific names. Give framework ItemStream implementations distinct names as well, because they derive state keys from those names. The file-reader checkpoint depends on this state being restored to the matching reader.

Persist only restart state

Keep a cursor, immutable manifest ID or small counter in the context. Do not put an entire receipt list, a live connection or a non-serializable service there. Large values increase repository writes and may exceed database column capacity. If a business audit must survive after metadata cleanup, write it to a domain table; ExecutionContext is a recovery mechanism, not an audit store. Repository assertions can inspect what was saved after a failed run.

Test a collision deliberately

Configure two readers in one step with different names, stop after a chunk, and verify both offsets are present under distinct keys. Restart and assert no duplicated or missing source reference. A green first execution says little about restore behavior. Change a component name only with a migration or an intentional new job identity, because old checkpoint keys may no longer match.

Implementation contract

Java
final class ReceiptCursor implements ItemStream {
    private long nextOffset;

    @Override public void update(ExecutionContext state) {
        state.putLong("receiptCursor.nextOffset", nextOffset);
    }

    @Override public void open(ExecutionContext state) {
        nextOffset = state.getLong("receiptCursor.nextOffset", 0L);
    }

    @Override public void close() {}
}

Cost and verification

A few primitive values are cheap to serialize. Context growth adds database I/O at checkpoints and can make recovery slower than replaying the source.

Common Mistakes

  • Do not give two ItemStreams the same state name in one step.
  • Do not store large row collections or live resources in ExecutionContext.
  • Do not rename checkpoint keys without planning what existing failed jobs will restore.

Read next

Spring Batch FlatFileItemReader: save state against an immutable source, Spring Batch restart tests: assert metadata rows, not repeated ID values, Spring Batch chunk restart: know which receipts committed, Spring Batch partition restart: preserve worker names and input slices, Spring Batch restart boundaries: recorded failure versus abrupt process loss.

spring
spring-batch
batch-executioncontext-key-ownership
Storage details