# 10. Resourceless vs. JDBC-backed: the dependency that makes chapter 7 possible [← Previous](09-corrections.md) | [README](../README.md) | [Next: Production checklist →](11-production-checklist.md) Everything in [chapter 7](07-restartability.md) depends on one dependency choice that is easy to get wrong on Spring Boot 4.1, because getting it wrong does not produce an error — the application starts, the job runs, nothing complains. Spring Boot 4.1 split Batch autoconfiguration into separate modules rather than one monolith: | Starter | Autoconfiguration class | What it provides | |---|---|---| | `spring-boot-starter-batch` | `BatchAutoConfiguration` | Batch infrastructure basics; a **resourceless** (in-memory, non-persistent) `JobRepository` if nothing more specific is configured | | `spring-boot-starter-batch-jdbc` | `BatchJdbcAutoConfiguration` | A real JDBC-backed `JobRepository`, plus `spring.batch.jdbc.initialize-schema` to create the `BATCH_*` tables | `spring-boot-starter-batch-jdbc` (this module's actual dependency, in [`pom.xml`](../pom.xml)) pulls in `spring-boot-starter-batch` transitively, so **both** autoconfiguration classes are normally on the classpath together, and `BatchJdbcAutoConfiguration` wins by providing the more specific `JobRepository` bean. Nothing about compiling or starting the application tells you which one actually won. ## Proving it, by turning the JDBC half off `--spring.autoconfigure.exclude=...BatchJdbcAutoConfiguration` removes the JDBC-backed `JobRepository` from the picture, leaving `BatchAutoConfiguration`'s resourceless one as the only candidate. Same job, same identifying job parameters, same `PRODUCT` table, run twice, in two separate JVMs: ```console -- run 1 -- REPORT: 58 products now in the PRODUCT table JOB FINISHED: status=COMPLETED exitCode=COMPLETED -- run 2: a second, completely fresh JVM, same jar, same job parameters, same PRODUCT table -- org.springframework.dao.DuplicateKeyException: ... Unique index or primary key violation ... VALUES ( /* 1 */ 'ABC-0001' ) JOB FINISHED: status=FAILED exitCode=FAILED ``` Full transcript: [`docs/output/11-resourceless-forgets-everything.txt`](output/11-resourceless-forgets-everything.txt). Run 2 does not throw `JobInstanceAlreadyCompleteException`, the exception you would expect for re-running an already-completed job (see [chapter 5](05-launching-and-jobparameters.md)). It does not know there was a run 1 at all. The resourceless `JobRepository` lives only in that JVM's heap; when the process exits, every `JobInstance`, `JobExecution`, and `StepExecution` it ever recorded goes with it. Run 2 starts `productImportJob` as if for the first time, tries to insert `ABC-0001` again, and collides with what run 1 already committed to the `PRODUCT` table — a table that, unlike the job repository, *is* backed by the same file-based H2 database both times. This is the practical failure mode: **the job repository's persistence and your own application data's persistence are two separate decisions**, and it is entirely possible to get the second one right (a real database, a real table) while getting the first one wrong (resourceless, because `-jdbc` was left off a dependency list or excluded by a profile without realizing what it carried). The symptom is not a startup error. It is "my restart didn't restart" or "why did this job double-insert everything," discovered in whatever environment happens to restart the JVM between runs — which, for anything running in a container orchestrator, is any redeploy, crash-restart, or scale-down/scale-up cycle.
How to check which one you actually have. Query## Going deeper - `BatchProperties` and `BatchJdbcProperties`, including `spring.batch.job.enabled`, `spring.batch.jdbc.initialize-schema`, and `spring.batch.jdbc.table-prefix`: the `spring-configuration-metadata.json` inside `spring-boot-batch-4.1.1.jar` and `spring-boot-batch-jdbc-4.1.1.jar` is the authoritative list, more current than any blog post including this one. - MongoDB-backed job repositories follow the identical pattern via `spring-boot-starter-batch-data-mongodb`, not covered by this module. [Next: Production checklist →](11-production-checklist.md)information_schema.tables(or your database's equivalent) for a table namedBATCH_JOB_INSTANCEafter your application starts. If it is not there, you have the resourceless job repository, whatever your dependency list looks like on paper — check for an exclusion inspring.autoconfigure.exclude, a conflictingJobRepositorybean of your own, or simply a missing-jdbc/-mongodbstarter.