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

Spring Batch source digest: reject changed rows before a restart

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

A persisted checkpoint is unsafe when the query result or source file changes under the same manifest ID.

Download Spring source kit

Bind bytes to identity

The file-backed fixture hashes its ordered source ID and unit pairs when it first sees a manifest. On a later launch it recomputes the digest before calling the launcher. The test changes ID 4 from 44 to 82 after a failed run. The relaunch is rejected as changed input, leaves the two committed target rows untouched and creates no second Batch execution.

Use a real snapshot in production

Hashing a mutable table at launch is a gate, not an immutable source. Another writer could change it after the digest check and before the Batch reader consumes it. Pin a file version, a database snapshot or a versioned staging table. Add the manifest identity, source version, count and digest to a reviewable record; the input guide explains why a pathname alone is insufficient.

Make replay conflicts explicit

The H2 writer keys output by source ID and can replace a previously written row. The digest prevents this tested changed-source relaunch, but it does not validate every record's provenance or an external side effect. A correction should get a new manifest and a documented relationship to the failed one. Reconciliation must still account for accepted, rejected and unprocessed IDs.

Checked excerpt

Java
String observedHash = sourceHash(jdbc);
String storedHash = jdbc.query(
    "SELECT source_hash FROM receipt_manifest WHERE manifest_id = ?",
    result -> result.next() ? result.getString(1) : null, manifestId);
if (storedHash != null && !storedHash.equals(observedHash)) {
    throw new IllegalStateException("source changed for manifest " + manifestId);
}

Cost and verification

Digesting n source rows costs O(n) reading time and a small fixed hash state. Pinning an immutable snapshot adds storage and retention work.

Common Mistakes

  • Do not treat a digest computed before the read as isolation from concurrent mutations.
  • Do not reuse the old manifest ID for corrected input.
  • Do not let an upsert hide changed source values.

Read next

Spring Batch restart input: pin the manifest before resuming a cursor, Spring Batch writers: use a stable source key when a chunk is replayed, Spring Batch killed worker: fence it, recover STARTED, then restart, Spring Batch reconciliation: report accepted and rejected receipt IDs.

spring
spring-boot
spring-batch
batch-source-digest-guard
Storage details