このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Batch ドキュメント 6.0.6 を使用してください!

Spring Batch 6.1 の新機能

依存関係のアップグレード

In this release, Spring dependencies are upgraded to the following versions:

  • Spring Framework 7.1

  • Spring Integration 7.2

  • Spring Data 2026.1.0

  • Spring LDAP 4.1

  • Spring AMQP 4.2

  • Spring Kafka 4.2

  • Micrometer 1.18

MongoDB ジョブリポジトリのコレクションプレフィックス

The MongoDB job repository now supports a configurable collection prefix, similar to the table prefix of the JDBC job repository. This makes it possible to run several applications against the same MongoDB database, or to isolate environments from each other:

@EnableBatchProcessing
@EnableMongoJobRepository(collectionPrefix = "MY_APP_")
class MyJobConfiguration {

	// job definition omitted

}

The prefix defaults to BATCH_, so existing applications are not affected. For more details, please refer to the コレクションプレフィックスの変更 section.

DefaultFormattingConversionService に基づくデフォルト変換サービス

The job repository and job explorer now build their default ConfigurableConversionService on top of Spring Framework’s DefaultFormattingConversionService instead of a set of hand-written converters. This is exposed through the new ConversionServiceFactory utility class:

ConfigurableConversionService conversionService = ConversionServiceFactory.createConversionService();

The default conversion service keeps the same formats Spring Batch has always used for job parameters (ISO_INSTANT for java.util.Date, and the standard ISO formats for LocalDate、LocalTime、LocalDateTime、ZonedDateTime、OffsetDateTime), while benefiting from the broader set of converters and formatters that DefaultFormattingConversionService provides out of the box. Existing extension points, such as JdbcDefaultBatchConfiguration#getConversionService() and the setConversionService setter on JobRepositoryFactoryBean、JobExplorerFactoryBean、AbstractJdbcBatchMetadataDao、DefaultJobParametersConverter, are unaffected and can still be used to fully customize job parameter conversion.

As a result, the previous custom converters (DateToStringConverter、StringToDateConverter、LocalDateToStringConverter、StringToLocalDateConverter、LocalTimeToStringConverter、StringToLocalTimeConverter、LocalDateTimeToStringConverter、StringToLocalDateTimeConverter) are now deprecated. See the 非推奨 section for more details.

非同期処理 API とローカルチャンキングは spring-batch-core に移行されました

AsyncItemProcessor、AsyncItemWriter、ChunkTaskExecutorItemWriter (used for local chunking) have been moved from spring-batch-integration to org.springframework.batch.core.step.item in spring-batch-core. These API only rely on a TaskExecutor and have no dependency on Spring Integration, so they no longer need to live in the integration module. This lets applications use asynchronous item processing and local chunking without pulling in spring-batch-integration and its transitive dependencies.

This is a packaging change only, and no functional changes are introduced. The classes in spring-batch-integration are kept as deprecated subclasses of their new counterparts in spring-batch-core for backward compatibility, and will be removed in a future release. Existing applications continue to work as-is, but are encouraged to migrate to the new package:

// before
import org.springframework.batch.integration.async.AsyncItemProcessor;
import org.springframework.batch.integration.async.AsyncItemWriter;
import org.springframework.batch.integration.chunk.ChunkTaskExecutorItemWriter;

// after
import org.springframework.batch.core.step.item.AsyncItemProcessor;
import org.springframework.batch.core.step.item.AsyncItemWriter;
import org.springframework.batch.core.step.item.ChunkTaskExecutorItemWriter;

RepositoryItemWriter におけるフラッシングサポート

RepositoryItemWriter now supports flushing the underlying Spring Data repository after writing a chunk, in two ways:

  • If the repository exposes a single method that both saves and flushes items, such as JpaRepository#saveAllAndFlush(Iterable), that method name can be set with setMethodName. RepositoryItemWriter now detects, once at initialization, whether the named method accepts an Iterable (in which case it is invoked once with the whole chunk) or a single item (in which case it is invoked once per item, as before):

RepositoryItemWriter<Foo> writer = new RepositoryItemWriter<>(jpaRepository);
writer.setMethodName("saveAllAndFlush");
  • 保存とフラッシュが別々の操作である場合、サブクラスで新しい flush メソッドをオーバーライドして、チャンクの書き込み後にリポジトリをフラッシュすることができます。repository フィールドは protected に変更され、サブクラスから直接アクセスできるようになりました。

public class FlushingRepositoryItemWriter<T> extends RepositoryItemWriter<T> {

	public FlushingRepositoryItemWriter(JpaRepository<T, ?> repository) {
		super(repository);
	}

	@Override
	protected void flush() {
		((JpaRepository<T, ?>) this.repository).flush();
	}

}

For more details, please refer to the RepositoryItemWriter section.

MultiResourceItemReaderBuilder における位置パターン

MultiResourceItemReaderBuilder now accepts resource location patterns directly, so resources no longer need to be resolved and injected before configuring the reader:

// before
@Bean
public MultiResourceItemReader<Foo> multiResourceReader() throws IOException {
	PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
	Resource[] resources = resourcePatternResolver.getResources("classpath:data/input/file-*.txt");
	return new MultiResourceItemReaderBuilder<Foo>()
					.delegate(flatFileItemReader())
					.resources(resources)
					.build();
}

// after
@Bean
public MultiResourceItemReader<Foo> multiResourceReader() {
	return new MultiResourceItemReaderBuilder<Foo>()
					.delegate(flatFileItemReader())
					.resources("classpath:data/input/file-*.txt")
					.build();
}

Each pattern is resolved with a PathMatchingResourcePatternResolver, so any resource prefix supported by Spring (file:、classpath:、classpath*:, and so on) can be used, in addition to Ant-style wildcards (、*、?). For more details, please refer to the ロケーションパターンを使用したリソースの指定 section.

新しい ResourcesItemReaderBuilder

This release introduces a builder for ResourcesItemReader, called ResourcesItemReaderBuilder. Like MultiResourceItemReaderBuilder, it can resolve resources directly from one or more location patterns:

// before
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
ResourcesItemReader reader = new ResourcesItemReader();
reader.setResources(resourcePatternResolver.getResources("file:/data/inputs/*.csv"));
reader.setName("resourcesReader");

// after
ResourcesItemReader reader = new ResourcesItemReaderBuilder()
				.resources("file:/data/inputs/*.csv")
				.name("resourcesReader")
				.build();

For more details, please refer to the ResourcesItemReader section.

新しい PageableItemReader

This release introduces PageableItemReader, a type-safe alternative to RepositoryItemReader. Instead of invoking a repository method reflectively by name, it takes a function from a Spring Data Pageable to a Slice, which is checked at compile time:

// before
RepositoryItemReader<Customer> reader = new RepositoryItemReaderBuilder<Customer>()
				.repository(customerRepository)
				.methodName("findAll")
				.sort(Sort.by(Sort.Direction.ASC, "id"))
				.pageSize(100)
				.name("customerReader")
				.build();

// after
PageableItemReader<Customer> reader = new PageableItemReaderBuilder<Customer>()
				.query(customerRepository::findAll)
				.sort(Sort.by(Sort.Direction.ASC, "id"))
				.pageSize(100)
				.name("customerReader")
				.build();

The sort can also be expressed with type-safe property references, which eliminates string-based property names:

PageableItemReader<Customer> reader = new PageableItemReaderBuilder<Customer>()
				.query(customerRepository::findAll)
				.sort(Sort.by(Sort.Direction.ASC, Customer::getId))
				.pageSize(100)
				.name("customerReader")
				.build();

For more details, please refer to the PageableItemReader section.

DatabaseType におけるスキーマの場所

DatabaseType now exposes the classpath locations of the schema creation and drop scripts for each supported database, through the new getProductSchema() and getProductSchemaDrop() methods. This avoids hard-coding these locations (and the risk of typos) when configuring a DataSource or a ResourceDatabasePopulator:

// before
new EmbeddedDatabaseBuilder()
    .addScript("/org/springframework/batch/core/schema-drop-h2.sql")
    .addScript("/org/springframework/batch/core/schema-h2.sql")
    .build();

// after
new EmbeddedDatabaseBuilder()
    .addScript(DatabaseType.H2.getProductSchemaDrop())
    .addScript(DatabaseType.H2.getProductSchema())
    .build();

For more details, please refer to the DDL スクリプトの例 section.

アイテムリーダーおよびライターのデフォルト名

Builders for item readers and writers that persist their state in the ExecutionContext (for example FlatFileItemReaderBuilder、JdbcCursorItemReaderBuilder、JdbcPagingItemReaderBuilder、RepositoryItemReaderBuilder, and others) no longer require an explicit name to be set when saveState is true:

// before: required an explicit name, or building the reader would fail
// after: builds successfully, using a default name
@Bean
public FlatFileItemReader<Foo> fooReader() {
    return new FlatFileItemReaderBuilder<Foo>()
                    .resource(resource)
                    .delimited()
                    .names("first", "second", "third")
                    .targetType(Foo.class)
                    .build();
}

This is possible because these readers and writers extend ItemStreamSupport, which already defaults the name to the short class name and overrides it with the Spring bean name when the reader or writer is declared as a bean. The strict name requirement in the builders was redundant with this existing behavior. An explicit name is still recommended, and required, when the default is not unique enough, such as when two instances of the same reader or writer type are used within the same step. For more details, please refer to the Custom `ItemReader` s and `ItemWriter`s section.

相互排他的なビルダーメソッドのコンパイル時安全性

A few builders exposed pairs of methods that configure mutually exclusive strategies, but allowed calling both on the same instance, only failing with an IllegalStateException when build() was called:

  • FlatFileItemReaderBuilder#targetType(Class) および #fieldSetMapper(FieldSetMapper)

  • FlatFileItemWriterBuilder#delimited()/#delimited(Consumer)、#formatted()/#formatted(Consumer)

  • JdbcBatchItemWriterBuilder#columnMapped() および #beanMapped()

These builders now use a staged DSL: calling one of the two methods returns a stage that exposes every other configuration method of the builder, except the conflicting one, so invalid combinations are now rejected by the compiler instead of at runtime:

// before: compiles, but throws IllegalStateException at build() time
new FlatFileItemReaderBuilder<Foo>()
    .name("fooReader")
    .resource(resource)
    .lineTokenizer(tokenizer)
    .targetType(Foo.class)
    .fieldSetMapper(fieldSetMapper) // IllegalStateException at build()
    .build();

// after: fieldSetMapper() is not available once targetType() has been called
new FlatFileItemReaderBuilder<Foo>()
    .name("fooReader")
    .resource(resource)
    .lineTokenizer(tokenizer)
    .targetType(Foo.class)
    .fieldSetMapper(fieldSetMapper) // compile error
    .build();

The tokenizer/line mapping methods (delimited()、fixedLength()、lineTokenizer()) can still be configured before or after targetType()/fieldSetMapper(), in any order.

This is a source and binary breaking change for code compiled against Spring Batch 6.0 that calls targetType()、fieldSetMapper()、delimited()/formatted() (on FlatFileItemWriterBuilder), or columnMapped()/beanMapped(), since the return type of these methods changed from the builder itself to a dedicated stage type. Code that only chains calls fluently (the vast majority of usages) needs no changes beyond a recompile; code that stores the return value in a variable typed as the builder class, or that relied on catching the IllegalStateException from an invalid combination, needs to be updated.

For more details, see issue #4888 [GitHub] (英語) 。

Avro reflection-based (de)serialization now requires trusted classes

Apache Avro 1.12.2 rejects reflection-based (de)serialization (as done by SpecificDatumReader/SpecificDatumWriter and their reflect-based counterparts, used by AvroItemReader/AvroItemWriter for SpecificRecord and plain Java item types) of classes that are not explicitly trusted, throwing a SecurityException at runtime otherwise. GenericRecord item types are not affected.

Trust the item type (and, transitively, any custom class reachable from its fields) with either of the org.apache.avro.SERIALIZABLE_CLASSES or org.apache.avro.SERIALIZABLE_PACKAGES system properties:

-Dorg.apache.avro.SERIALIZABLE_PACKAGES=com.example.domain

or programmatically, through org.apache.avro.util.ClassSecurityValidator. See that class’s Javadoc for details.

This is a breaking change for applications that use AvroItemReader/ AvroItemWriter with a SpecificRecord or plain Java item type: such jobs now fail at runtime unless the item type is explicitly trusted as shown above.

JDBC DAOs migrated to JdbcClient

The JDBC implementations of the job repository DAOs (JdbcJobInstanceDao、JdbcJobExecutionDao、JdbcStepExecutionDao、JdbcExecutionContextDao) now use Spring Framework’s JdbcClient instead of JdbcOperations to access the batch metadata tables. This gives them named parameters and a single fluent API for queries, updates and batch updates.

The client is a required collaborator, so it is now passed to the constructor rather than set afterwards:

// before
JdbcJobInstanceDao jobInstanceDao = new JdbcJobInstanceDao();
jobInstanceDao.setJdbcTemplate(new JdbcTemplate(dataSource));
jobInstanceDao.setJobInstanceIncrementer(incrementer);
jobInstanceDao.afterPropertiesSet();

// after
JdbcJobInstanceDao jobInstanceDao = new JdbcJobInstanceDao(JdbcClient.create(dataSource));
jobInstanceDao.setJobInstanceIncrementer(incrementer);
jobInstanceDao.afterPropertiesSet();

Accordingly, AbstractJdbcBatchMetadataDao#setJdbcTemplate(JdbcOperations) and #getJdbcTemplate() are deprecated in favor of the new constructor and of #getJdbcClient(). See the 非推奨 section for more details.

Applications that configure the job repository through @EnableBatchProcessing、@EnableJdbcJobRepository、JdbcDefaultBatchConfiguration、JdbcJobRepositoryFactoryBean or JobExplorerFactoryBean are not affected, as these build the DAOs themselves.

This is a source and binary breaking change for code compiled against Spring Batch 6.0 that instantiates these DAOs directly, since their no-argument constructors have been removed. Such code needs to pass a JdbcClient to the constructor as shown above.

For more details, see issue #4804 [GitHub] (英語) 。

@JobParameter annotation for injecting job parameters

Injecting a job parameter into a job or step scoped bean used to require a SpEL expression, which is a string that is only evaluated at runtime and is easy to get wrong. The new @JobParameter annotation is a shorter alternative that defaults the name of the job parameter to the name of the annotated field or parameter:

// before
@Bean
@StepScope
public FlatFileItemReader<Foo> fooReader(@Value("#{jobParameters['inputFile']}") String inputFile) {
    return new FlatFileItemReaderBuilder<Foo>()
                    .resource(new FileSystemResource(inputFile))
                    // other properties omitted
                    .build();
}

// after
@Bean
@StepScope
public FlatFileItemReader<Foo> fooReader(@JobParameter String inputFile) {
    return new FlatFileItemReaderBuilder<Foo>()
                    .resource(new FileSystemResource(inputFile))
                    // other properties omitted
                    .build();
}

The name can also be specified explicitly, for example @JobParameter("input.file.name"), which is required when it is not a valid Java identifier or differs from the name of the field or parameter. @JobParameter can be used on fields and on method or constructor parameters, and is supported with @EnableBatchProcessing and DefaultBatchConfiguration.

@JobParameter is equivalent to @Value("#{jobParameters['name']}"), so it behaves the same way: it is meant for beans defined in the job or step scope, and a missing job parameter is injected as null. When the name is omitted on a method or constructor parameter, the code must be compiled with the -parameters flag (which is the default with the Spring Boot Maven and Gradle plugins), otherwise an exception is thrown.

新しい RemoteChunkingManagerBuilder

The new RemoteChunkingManagerBuilder is the counterpart of RemoteChunkingWorkerBuilder for configuring the manager step of a remote chunking setup. It only holds the settings that are specific to remote chunking (channels, messaging template, maximum number of wait timeouts and throttle limit), and chunk(int) returns a standard ChunkOrientedStepBuilder for everything else. The resulting step is a ChunkOrientedStep, and the builder does not expose any deprecated API:

// before
@Bean
public TaskletStep managerStep() {
    return this.managerStepBuilderFactory.get("managerStep")
                .chunk(100)
                .reader(itemReader())
                .outputChannel(requests())
                .inputChannel(replies())
                .build();
}

// after
@Bean
public Step managerStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new RemoteChunkingManagerBuilder("managerStep", jobRepository)
                .outputChannel(requests())
                .inputChannel(replies())
                .chunk(100)
                .reader(itemReader())
                .transactionManager(transactionManager)
                .build();
}
The channels must be set before calling chunk(int). Also, the transaction manager defaults to a resourceless one, whereas RemoteChunkingManagerStepBuilderFactory used the transaction manager of the application context, so it should be set explicitly if the item reader of the manager step needs a transactional resource.

RemoteChunkingManagerStepBuilder and RemoteChunkingManagerStepBuilderFactory are deprecated in favor of RemoteChunkingManagerBuilder.

For more details, please refer to the リモートチャンキング section.

新しい DefaultChunkProcessor

SimpleChunkProcessor has been deprecated since 6.0 as part of the legacy chunk-oriented processing engine, but it was still the way to process chunks outside of a step: in a remote chunking worker (ChunkProcessorChunkRequestHandler) or with a ChunkTaskExecutorItemWriter. The new DefaultChunkProcessor is its replacement for those use cases. It is a minimal implementation of ChunkProcessor that applies an optional ItemProcessor to each item of a chunk and writes the result with an ItemWriter. Items filtered by the item processor are counted as such in the StepContribution, and failures are rethrown as is.

Unlike SimpleChunkProcessor, it does not support listeners, does not record metrics, and is configured through its constructor:

// before
SimpleChunkProcessor<Integer, Integer> chunkProcessor = new SimpleChunkProcessor<>(itemProcessor, itemWriter);

// after
DefaultChunkProcessor<Integer, Integer> chunkProcessor = new DefaultChunkProcessor<>(itemProcessor, itemWriter);

RemoteChunkingWorkerBuilder now uses it internally. This is also the equivalent to use when replacing the <remote-chunking-worker> element of the batch-integration XML namespace (deprecated since 6.0) with plain XML bean definitions.

JsonLineMapper agnostic to the JSON library

JsonLineMapper could only map each line of a JSON Lines file to a Map<String, Object>, and only with Jackson. It is now generic and delegates the conversion of a line to a new JsonObjectUnmarshaller collaborator, the counterpart of JsonObjectMarshaller. This makes it independent of the JSON library and able to map lines to any type, such as a domain class or a record. Implementations based on Jackson (JacksonJsonObjectUnmarshaller) and Gson (GsonJsonObjectUnmarshaller) are provided:

record Trade(String isin, int quantity, double price, String customer) {
}

// before: items could only be maps, mapped with Jackson
FlatFileItemReader<Map<String, Object>> reader = new FlatFileItemReaderBuilder<Map<String, Object>>()
				.name("tradeReader")
				.resource(resource)
				.lineMapper(new JsonLineMapper())
				.build();

// after: items can be of any type, mapped with Jackson or Gson
FlatFileItemReader<Trade> reader = new FlatFileItemReaderBuilder<Trade>()
				.name("tradeReader")
				.resource(resource)
				.lineMapper(new JsonLineMapper<>(new JacksonJsonObjectUnmarshaller<>(Trade.class)))
				// or .lineMapper(new JsonLineMapper<>(new GsonJsonObjectUnmarshaller<>(Trade.class)))
				.build();

A custom JsonMapper or Gson can be provided to the unmarshaller, for example new JacksonJsonObjectUnmarshaller<>(jsonMapper, Trade.class). For parameterized target types, which cannot be expressed with a Class, the unmarshallers accept a Jackson TypeReference or a Gson TypeToken. JsonObjectUnmarshaller is a functional interface, so a custom implementation can be provided as a lambda.

The no-argument constructor and the constructor that takes a JsonMapper are deprecated. Code that still maps lines to a Map<String, Object> should provide the unmarshaller explicitly:

// before
LineMapper<Map<String, Object>> lineMapper = new JsonLineMapper();
LineMapper<Map<String, Object>> customLineMapper = new JsonLineMapper(jsonMapper);

// after
LineMapper<Map<String, Object>> lineMapper = new JsonLineMapper<>(
		new JacksonJsonObjectUnmarshaller<>(new TypeReference<Map<String, Object>>() {}));
LineMapper<Map<String, Object>> customLineMapper = new JsonLineMapper<>(
		new JacksonJsonObjectUnmarshaller<>(jsonMapper, new TypeReference<Map<String, Object>>() {}));

where TypeReference is tools.jackson.core.type.TypeReference. See the 非推奨 section for more details.

This is a source and binary breaking change for code compiled against Spring Batch 6.0 that uses the raw JsonLineMapper type and calls mapLine directly on it, since the return type of mapLine is now the type parameter instead of Map<String, Object>. Such code needs to declare the variable with its type argument, or to type it as LineMapper<Map<String, Object>>. Also, mapLine no longer declares throws Exception, and a line that cannot be parsed now causes a ParseException wrapping the exception of the JSON library, instead of the exception of the JSON library itself. Code that only passes the mapper to a reader (the vast majority of usages) needs no changes beyond a recompile.

For more details, please refer to the JsonLineMapper section.

新しい JsonLineAggregator

This release introduces JsonLineAggregator, a LineAggregator that makes it possible to write items to a JSON 行 (英語) file with a FlatFileItemWriter. It is the writer-side counterpart of JsonLineMapper and, like it, it is agnostic to the JSON library: it delegates the conversion of an item to a JsonObjectMarshaller, so either the Jackson or the Gson implementation can be used:

// before: a custom LineAggregator was needed
// after
FlatFileItemWriter<Trade> writer = new FlatFileItemWriterBuilder<Trade>()
				.name("tradeWriter")
				.resource(new FileSystemResource("trades.jsonl"))
				.lineAggregator(new JsonLineAggregator<>(new JacksonJsonObjectMarshaller<>()))
				.build();
Each item is written as a single line, so the marshaller must produce a JSON object that fits on one line, which is the case of the default Jackson and Gson marshallers.

For more details, please refer to the JsonLineAggregator section.

非推奨

The following features have been deprecated in Spring Batch 6.1:

  • Deprecate Apache Derby support (DatabaseType.DERBY, DerbyPagingQueryProvider and the Derby DDL scripts), scheduled for removal in version 7.0.0

  • Deprecate the legacy date/time converters (DateToStringConverter、StringToDateConverter、LocalDateToStringConverter、StringToLocalDateConverter、LocalTimeToStringConverter、StringToLocalTimeConverter、LocalDateTimeToStringConverter、StringToLocalDateTimeConverter) in favor of ConversionServiceFactory#createConversionService(), scheduled for removal in version 7.0.0

  • Deprecate StepExecution#getJobExecutionId() and StepExecution#getJobParameters() in favor of StepExecution#getJobExecution(), scheduled for removal in version 7.0

  • Deprecate JobExecution#getJobInstanceId() in favor of JobExecution#getJobInstance(), scheduled for removal in version 7.0

  • Deprecate RepositoryItemReader#setSorts(Map) and RepositoryItemReader#setRepository(PagingAndSortingRepository) in favor of passing the sorts and the repository to the constructor, scheduled for removal in version 7.0

  • Deprecate RepositoryItemWriter#setRepository(CrudRepository) in favor of passing the repository to the constructor, scheduled for removal in version 7.0

  • Deprecate org.springframework.batch.integration.async.AsyncItemProcessor、org.springframework.batch.integration.async.AsyncItemWriter、org.springframework.batch.integration.chunk.ChunkTaskExecutorItemWriter in favor of their counterparts in org.springframework.batch.core.step.item, see the Async processing API and local chunking moved to spring-batch-core section for more details

  • Deprecate AbstractJdbcBatchMetadataDao#setJdbcTemplate(JdbcOperations) in favor of passing a JdbcClient to the constructor of the JDBC DAOs, and AbstractJdbcBatchMetadataDao#getJdbcTemplate() in favor of AbstractJdbcBatchMetadataDao#getJdbcClient(), see the JDBC DAOs migrated to JdbcClient section for more details. Scheduled for removal in version 7.0

  • Deprecate RemoteChunkingManagerStepBuilder and RemoteChunkingManagerStepBuilderFactory in favor of RemoteChunkingManagerBuilder, see the New RemoteChunkingManagerBuilder section for more details. Scheduled for removal in version 7.0

  • Deprecate JsonLineMapper() and JsonLineMapper(JsonMapper) in favor of JsonLineMapper(JsonObjectUnmarshaller), see the JsonLineMapper agnostic to the JSON library section for more details. Scheduled for removal in version 7.0

  • Deprecate JobRepository#getJobInstanceCount(String)、JobExplorer#getJobInstanceCount(String)、JobInstanceDao#getJobInstanceCount(String) in favor of countJobInstances(String), and JobRepository#getStepExecutionCount(JobInstance, String) and JobExplorer#getStepExecutionCount(JobInstance, String) in favor of countStepExecutions(JobInstance, String). These methods cannot soundly determine whether a job or step name is unknown, as opposed to simply never having been persisted or executed yet; that validation belongs at the job operator level, where the job registry is available. Scheduled for removal in version 7.0