Exposed Spring Boot Batch Integration
Latest stable Based on Exposed release 1.11.0
Exposed range partitioning, keyset restart, and chunk writers inside Spring Boot’s Spring Batch runtime.
Problem
Section titled “Problem”This module adds Exposed-aware Partitioner, ItemStreamReader, and ItemWriter implementations plus an overridable partition executor to a Spring Batch application. It relies on Spring Boot’s BatchAutoConfiguration for job infrastructure. Do not add @EnableBatchProcessing: in the supported Boot configuration it disables the Boot Batch auto-configuration this integration expects.
The adjacent lightweight runtime has a different ownership model:

When to use it
Section titled “When to use it”Use this module when the application already uses Spring Batch jobs, steps, chunk commits, ExecutionContext, restart metadata, and partition execution, but wants Exposed to read and write application tables. Use Exposed Batch Utilities instead when a small coroutine runner with its own execution repository is sufficient.
Coordinates
Section titled “Coordinates”Import the ecosystem BOM and omit the module version:
dependencies { implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>")) implementation("io.github.bluetape4k.exposed:bluetape4k-exposed-spring-boot-batch")}Core concepts
Section titled “Core concepts”ExposedRangePartitioner reads the minimum and maximum of a monotonic Long key and writes minId and maxId into each partition’s ExecutionContext. ExposedKeysetItemReader restores those bounds plus lastKey, then reads column > lastKey AND column <= maxId ORDER BY column ASC LIMIT pageSize. Its update method saves lastKey, so Spring Batch persists progress at a committed chunk boundary.
The Exposed writers execute directly in the Spring Batch chunk transaction managed through SpringTransactionManager. They intentionally do not open a nested Exposed transaction {} block.
Quick start
Section titled “Quick start”Keep Boot Batch auto-configuration enabled, define the job and chunk-oriented worker step, and attach an ExposedRangePartitioner to the manager step. Create a step-scoped ExposedKeysetItemReader for each partition and choose ExposedItemWriter, ExposedUpdateItemWriter, or ExposedUpsertItemWriter for the worker step.
spring: batch: job: enabled: false # launch jobs explicitly when that matches the service lifecycleDo not add @EnableBatchProcessing merely to make the job run; diagnose Boot Batch auto-configuration instead.
API by task
Section titled “API by task”- Partition a
Column<Long>withExposedRangePartitioner; useforEntityIdfor aLongIdTable. - Read a partition with
ExposedKeysetItemReader; use itsforEntityIdfactory for DAO ID tables. - Insert chunks with
ExposedItemWriter, update each key withExposedUpdateItemWriter, or use database-supported batch upsert throughExposedUpsertItemWriter. - Inject the bean named
batchPartitionTaskExecutorinto a partition handler, or provide a bean with that name to replace the default. - Configure jobs with the helpers in
BatchJobExtensions.ktwhile leaving transaction ownership with Spring Batch.
Recommended patterns
Section titled “Recommended patterns”Partition only on a unique, monotonic key whose range remains reasonably stable during a run. Keep gridSize, executor concurrency, database pool size, and downstream write capacity aligned. Use keyset ordering without gaps in the comparison semantics. Prefer upsert or another idempotent write when an operator may restart a job after uncertain external effects.
Integrations
Section titled “Integrations”ExposedBatchAutoConfiguration runs after BatchAutoConfiguration and is conditional on Spring Batch Job. It contributes only ExposedBatchProperties and, when enabled and missing, batchPartitionTaskExecutor. The default is SimpleAsyncTaskExecutor with virtual threads enabled; an application-defined bean of the same name takes precedence.
Configuration
Section titled “Configuration”bluetape4k.batch.executor.enabled=false disables the default executor. virtual-threads defaults to true; concurrency-limit defaults to twice the available processors; await-termination-seconds defaults to 30. These are executor limits, not database capacity guarantees. Set the reader pageSize, partition gridSize, Spring Batch chunk size, and datasource pool together from measurements.
Failure modes
Section titled “Failure modes”- Boot Batch infrastructure is missing after adding
@EnableBatchProcessing: remove the annotation and let Boot auto-configure it. - A partition repeats or misses rows: verify a unique monotonic key, stable
minId/maxId, andlastKeyrestoration. - Restart begins before expected data: only a committed chunk advances durable Spring Batch
ExecutionContext; inspect the last committed step state. - Writer reports no Exposed transaction: verify the step uses the
SpringTransactionManagerconnected to the same datasource and do not open an unrelated nested transaction. - Virtual-thread concurrency overwhelms the pool: reduce
concurrency-limit, partition count, or chunk pressure; virtual threads do not create database connections.
Operations
Section titled “Operations”Observe job and step status, partition name, minId, maxId, lastKey, read/write/skip counts, commit count, executor concurrency, pool acquisition, and chunk latency. On restart, compare the restored lastKey with the last committed business rows. An in-memory reader buffer is not durable; ExecutionContext is the restart authority.
Testing
Section titled “Testing”Run the exact module tests:
./gradlew :bluetape4k-exposed-spring-boot-batch:testVerify Boot auto-configuration without @EnableBatchProcessing, default and overridden executor beans, empty and uneven ranges, stable partition bounds, keyset restart from lastKey, chunk rollback, restart after a committed chunk, and insert/update/upsert writers participating in the existing chunk transaction without a nested transaction.
Workshops and learning path
Section titled “Workshops and learning path”Compare Exposed Batch Utilities before choosing a runtime, then read transaction boundaries. Use the end-to-end and restart tests in this module as the executable Spring Batch contract.
Limitations
Section titled “Limitations”Range partitioning assumes a Long-compatible, unique, monotonic key and is best when large inserts or deletes do not reshape the range during execution. lastKey records read progress at Spring Batch checkpoints; it does not make external side effects atomic. The default virtual-thread executor is optional and replaceable, and must still respect database pool limits.
Release diagrams
Section titled “Release diagrams”These diagrams are loaded directly from README assets published with the 1.11.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.
Spring Batch Exposed integration map
Section titled “Spring Batch Exposed integration map”Release README: spring-boot/batch-exposed/README.md
Partitioned keyset restart flow
Section titled “Partitioned keyset restart flow”Release README: spring-boot/batch-exposed/README.md

