Add spring-batch: jobs, steps, chunk processing and restartability on Boot 4.1

Companion code for "Spring Batch on Boot 4.1: Jobs, Steps, Chunk Processing and
Restartability". A productImportJob configured three ways by profile against a
poisoned CSV row, run as real java -jar processes (not just JUnit) so the
restart story is genuine: a chunk fails and rolls back, the process exits, a
brand-new JVM against the same file-based H2 database resumes at the exact
next unread row (READ_COUNT 20, not 60) and completes.

Findings the build pins:
- StepBuilder.chunk(int, PlatformTransactionManager) still compiles in Batch
  6.0.5 but returns the legacy SimpleStepBuilder; chunk(int) returns the new
  ChunkOrientedStepBuilder, and only the latter is used here.
- Two different ExecutionContext classes now exist in two different packages
  (infrastructure.item vs core.repository.persistence) with different shapes.
- spring-boot-starter-batch alone gives a resourceless JobRepository that
  forgets every JobInstance the moment the JVM exits; spring-boot-starter-
  batch-jdbc is what makes the restart demo possible at all, demonstrated by
  excluding BatchJdbcAutoConfiguration and watching a "restart" collide with
  the previous run's own data instead of resuming it.
- A migration-guide summary claiming CommandLineJobRunner was removed in 6.0
  is wrong -- javap against the real jar shows @Deprecated(forRemoval=true),
  not removed.
- RepeatStatus moved from core.repeat to infrastructure.repeat, caught by the
  compiler rather than by reading docs.

11 documentation chapters, 10 captured transcripts (unit tests, javap output,
and real two-JVM scenario runs), all regenerated by scripts/run-all.sh.

Fixed after push: three dead docs.spring.io links in the doc chapters
(readersAndWriters/* and chunk-oriented-processing/*.html paths moved when
Spring Batch 6 reorganized its reference docs; corrected to the current
readers-and-writers/*, processor.html and chunk-oriented-processing.html
paths, verified 200 via curl before committing).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019DXsJ1zpikbA1MQJN6RqFA
This commit is contained in:
Claude
2026-09-13 06:37:46 +00:00
parent a9867c0423
commit b81af72bc3
40 changed files with 2001 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
# 9. Corrections found while writing this
[&larr; Previous](08-skip-vs-restart.md) | [README](../README.md) | [Next: Resourceless vs. JDBC-backed &rarr;](10-resourceless-vs-jdbc.md)
Per the verification discipline this repository follows, here is what was wrong in an earlier
draft, and how it was caught &mdash; recorded honestly rather than silently fixed, because the
mistake is often as informative as the correct answer.
## "CommandLineJobRunner was removed in 6.0" &mdash; wrong, it is deprecated
A community-written Spring Batch 6.0 migration guide describes `CommandLineJobRunner` as removed
outright, in a list alongside classes that genuinely were deleted
(`ChunkListenerSupport`, `JobExecutionListenerSupport`, and others). An early draft of this
article repeated that claim. Checking the actual `spring-batch-core-6.0.5.jar` shows it is wrong:
```console
$ javap -verbose -cp spring-batch-core-6.0.5.jar org.springframework.batch.core.launch.support.CommandLineJobRunner | grep -A3 "^public class\|Deprecated"
public class org.springframework.batch.core.launch.support.CommandLineJobRunner
...
Deprecated: true
RuntimeVisibleAnnotations:
0: #505(#506=s#507,#508=Z#509)
java.lang.Deprecated(
since="6.0"
forRemoval=true
)
```
Full transcript: [`docs/output/09-commandlinejobrunner-deprecated-not-removed.txt`](output/09-commandlinejobrunner-deprecated-not-removed.txt).
The class is present, loadable, and functional in 6.0.5 &mdash; it carries
`@Deprecated(since = "6.0", forRemoval = true)`, which means "stop using this, it will be
deleted in a future release," not "this is already gone." `CommandLineJobOperator` is the
replacement, and it does exist alongside it in the same package.
This is the article's own self-correction pass working as intended: a claim sourced from a
third-party summary of a migration guide, not from a primary artifact, was treated as unverified
until checked. The general rule this project follows (see the parent repository's process notes)
is that a migration guide's own prose is not itself a primary source for "removed vs.
deprecated" &mdash; the jar is.
## `RepeatStatus` package move, caught by the compiler rather than by reading docs
Writing [`BatchConfig.reportTasklet`](../src/main/java/com/ankurm/batch/config/BatchConfig.java),
the first draft imported `org.springframework.batch.core.repeat.RepeatStatus` &mdash; the
Spring Batch 5.x location, from memory and from older examples. `mvn -B -o compile` reported:
```
[ERROR] .../BatchConfig.java:[93,57] package org.springframework.batch.core.repeat does not exist
```
The fix was `org.springframework.batch.infrastructure.repeat.RepeatStatus`, matching the general
package reorganization covered in [chapter 2](02-anatomy-of-a-job.md). No migration guide was
consulted for this one; the compiler error was sufficient, which is the point &mdash; letting
`javac` tell you where an API moved is faster and more reliable than trying to remember or look
up a package reorganization table.
[Next: Resourceless vs. JDBC-backed &rarr;](10-resourceless-vs-jdbc.md)