Readers and writers persist small restart values in an ExecutionContext; colliding keys can restore the wrong cursor or overwrite another component.
Spring Batch ExecutionContext keys: give each stream its own checkpoint
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
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.
