Spring Batch 6.1.0-M1 Aligns The 6.1 Platform Train


Spring Batch tagged 6.1.0-M1 against Spring Framework 7.1, then set main back to 6.1.0-SNAPSHOT. The rest of the week is POM pins, README version lines, and Javadoc @since corrections that finally name the 6.0.5 reader and serializer APIs. Eight commits, 24 files, 57 insertions, 45 deletions: a milestone cut, not a feature dump.

The volume is the tell. Most of the diff lives in module POMs. Operators should still read the Javadoc commit, because that is where FlatFileItemReader record caps and the execution context deserializer filter are marked as 6.0.5 instead of the versions they were first tagged with.

The release commit is a version edit. Project version goes from 6.1.0-SNAPSHOT to 6.1.0-M1 in the root pom.xml and in every module POM (spring-batch-core, spring-batch-infrastructure, spring-batch-integration, spring-batch-test, spring-batch-samples, spring-batch-docs, spring-batch-bom). java.version stays 17.

The cost is the Spring BOM shift. 6.1.0-M1 is aligned to:

  • Spring Framework 7.1.0-M1 (was 7.0.8)
  • Spring Integration 7.2.0-M1 (was 7.0.5)
  • Micrometer 1.18.0-M1 (was 1.16.6)
  • Spring Data BOM 2026.1.0-M1 (was 2025.1.6)
  • Spring Kafka 4.2.0-M1 (was 4.0.6)
  • Spring AMQP 4.2.0-M1 (was 4.0.4)
  • Spring LDAP 4.1.1 (was 4.0.4)
  • Micrometer Tracing 1.8.0-M1 (was 1.6.6)

Jobs still on Batch 6.0 stay on Framework 7.0. The 6.1 milestone is the first public pin to the 7.1 line. Kafka 4.2, AMQP 4.2, and Data 2026.1.0 ride along. Teams that manage those BOMs independently need a matching bump, not a Batch only bump.

A later development version commit set every module back to 6.1.0-SNAPSHOT. The Spring pins stayed at the M1 coordinates until the snapshot sweep at the end of the window.

Before the tag, Redis drivers moved in the same root POM. Lettuce went from 7.5.2.RELEASE to 7.6.0.RELEASE. Jedis went from 7.5.2 to 8.0.0.

RedisItemReader and RedisItemWriter talk to Redis through Spring Data Redis RedisTemplate, not through those clients directly. The pins still matter for tests, samples, and anyone who lets Batch’s POM manage Lettuce or Jedis.

Jedis 8 is a major. If a job constructs a Jedis client by hand, or pins Jedis next to Spring Data Redis, read the Jedis 8 notes before copying this POM. Lettuce 7.6 is a minor on the 7.x line and is the smaller risk. Nothing in this window changes the reader contract: RedisItemReader is still not thread safe and still not restartable.

The Javadoc fix looks small. It is the most operator visible change in the window.

@since tags on FlatFileItemReader.java and FlatFileItemReaderBuilder.java moved from 6.0.4 to 6.0.5. Same for DEFAULT_FILTER_PATTERN and setObjectInputFilter on DefaultExecutionContextSerializer.java, which had been tagged 5.2.7.

Those APIs shipped. FlatFileItemReader now bounds the multiline record accumulator:

public static final int DEFAULT_MAX_LINES_PER_RECORD = 1_000;
public static final int DEFAULT_MAX_BYTES_PER_RECORD = 1_048_576;

DefaultRecordSeparatorPolicy and JsonRecordSeparatorPolicy fold quoted or braced input across lines. An unbalanced quote used to pin a CPU core and grow a single record without a ceiling. The accumulator now throws FlatFileParseException at 1000 lines or 1 MiB of characters, whichever hits first. setMaxLinesPerRecord and setMaxBytesPerRecord raise the ceiling. Integer.MAX_VALUE disables it. Do not disable it on untrusted files.

The matching test, FlatFileItemReaderRecordCapTests.java, got a license header the same day. The tests drive an unbalanced quote and an unbalanced brace past the cap and assert the parse exception. A quoted three line record still round trips inside the default bound.

On the job repository side, DefaultExecutionContextSerializer installs an ObjectInputFilter before any readObject. The default pattern allows java.lang.*, java.util.*, java.time.*, java.math.*, java.sql.*, java.net.URL, javax.xml.namespace.QName, and org.springframework.batch.**, then rejects everything else with !*. Custom types stored in ExecutionContext fail deserialize unless the job calls setObjectInputFilter with a wider pattern.

The README news line records the 20 August 2026 pair: 6.0.5 on the stable line and 6.1.0-M1 on the 6.1 line. The getting started tutorial now pins spring-batch-core at 6.0.5, not 6.0.4. New copies of that snippet land on the release that actually contains the caps and the serializer filter.

After the tag, Spring dependencies in the root POM left the M1 coordinates:

<spring-framework.version>7.1.0-SNAPSHOT</spring-framework.version>
<spring-integration.version>7.2.0-SNAPSHOT</spring-integration.version>
<micrometer.version>1.18.0-SNAPSHOT</micrometer.version>
<spring-data-bom.version>2026.1.0-SNAPSHOT</spring-data-bom.version>
<spring-kafka.version>4.2.0-SNAPSHOT</spring-kafka.version>
<spring-amqp.version>4.2.0-SNAPSHOT</spring-amqp.version>
<spring-ldap.version>4.1.2-SNAPSHOT</spring-ldap.version>

Spring LDAP is the odd one. M1 used 4.1.1. main now tracks 4.1.2-SNAPSHOT, a patch ahead of the milestone. Micrometer Tracing moved from 1.8.0-M1 to 1.8.0-SNAPSHOT.

Building main is no longer a replay of 6.1.0-M1. It is the 6.1 development line against live Spring snapshots. CI that checks out main and expects M1 coordinates will drift.

Pin artifacts on purpose. Production jobs that want the milestone should depend on 6.1.0-M1 and the M1 Spring BOMs from that tag. Jobs that want the reader caps and the serializer allowlist without leaving 6.0 should take 6.0.5. Do not mix those lines.

Raise maxLinesPerRecord and maxBytesPerRecord before pointing FlatFileItemReader at legitimate multiline JSON or quoted CSV that can exceed 1000 lines or 1 MiB per record. The default is a safety bound, not a format limit you can ignore.

If ExecutionContext holds application types, install a custom ObjectInputFilter before the first restart. The default allowlist is narrow on purpose.