|
This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Batch Documentation 6.0.6! |
What’s new in Spring Batch 6.1
This section highlights the major changes in Spring Batch 6.1. For the complete list of changes, please refer to the release notes.
Spring Batch 6.1 includes the following features and improvements:
Dependencies upgrade
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
Collection prefix for the MongoDB job repository
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
Changing the Collection Prefix
section.
Default conversion service based on 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, and 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
setters on JobRepositoryFactoryBean, JobExplorerFactoryBean,
AbstractJdbcBatchMetadataDao, and 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, and
StringToLocalDateTimeConverter) are now deprecated. See the
Deprecations section for more details.
Async processing APIs and local chunking moved to spring-batch-core
AsyncItemProcessor, AsyncItemWriter, and ChunkTaskExecutorItemWriter (used for
local chunking) have been moved from spring-batch-integration to
org.springframework.batch.core.step.item in spring-batch-core. These APIs 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;
Flushing support in 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 withsetMethodName.RepositoryItemWriternow detects, once at initialization, whether the named method accepts anIterable(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");
-
If saving and flushing are separate operations, the new
flushmethod can be overridden in a subclass to flush the repository after the chunk has been written. Therepositoryfield is nowprotectedso that subclasses can access it directly:
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.
Location patterns in 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 (, *, and ?). For more details, please refer to
the Specifying
Resources With a Location Pattern section.
New 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.
New 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.
Schema locations in 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 Example DDL Scripts section.
Default name for item readers and writers
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.
Compile-time safety for mutually exclusive builder methods
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)and#fieldSetMapper(FieldSetMapper) -
FlatFileItemWriterBuilder#delimited()/#delimited(Consumer)and#formatted()/#formatted(Consumer) -
JdbcBatchItemWriterBuilder#columnMapped()and#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.
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 and 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 Deprecations 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.
@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.
|
For more details, please refer to the
Late Binding of Job and Step Attributes section, and
see issue #5563.
New 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 Remote Chunking section.
New 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
Deprecations 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.
New JsonLineAggregator
This release introduces JsonLineAggregator, a LineAggregator that makes it possible to
write items to a JSON Lines 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.
Deprecations
The following features have been deprecated in Spring Batch 6.1:
-
Deprecate Apache Derby support (
DatabaseType.DERBY,DerbyPagingQueryProviderand the Derby DDL scripts), scheduled for removal in version 7.0.0 -
Deprecate the legacy date/time converters (
DateToStringConverter,StringToDateConverter,LocalDateToStringConverter,StringToLocalDateConverter,LocalTimeToStringConverter,StringToLocalTimeConverter,LocalDateTimeToStringConverterandStringToLocalDateTimeConverter) in favor ofConversionServiceFactory#createConversionService(), scheduled for removal in version 7.0.0 -
Deprecate
StepExecution#getJobExecutionId()andStepExecution#getJobParameters()in favor ofStepExecution#getJobExecution(), scheduled for removal in version 7.0 -
Deprecate
JobExecution#getJobInstanceId()in favor ofJobExecution#getJobInstance(), scheduled for removal in version 7.0 -
Deprecate
RepositoryItemReader#setSorts(Map)andRepositoryItemReader#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, andorg.springframework.batch.integration.chunk.ChunkTaskExecutorItemWriterin favor of their counterparts inorg.springframework.batch.core.step.item, see the Async processing APIs and local chunking moved tospring-batch-coresection for more details -
Deprecate
AbstractJdbcBatchMetadataDao#setJdbcTemplate(JdbcOperations)in favor of passing aJdbcClientto the constructor of the JDBC DAOs, andAbstractJdbcBatchMetadataDao#getJdbcTemplate()in favor ofAbstractJdbcBatchMetadataDao#getJdbcClient(), see the JDBC DAOs migrated toJdbcClientsection for more details. Scheduled for removal in version 7.0 -
Deprecate
RemoteChunkingManagerStepBuilderandRemoteChunkingManagerStepBuilderFactoryin favor ofRemoteChunkingManagerBuilder, see the NewRemoteChunkingManagerBuildersection for more details. Scheduled for removal in version 7.0 -
Deprecate
JsonLineMapper()andJsonLineMapper(JsonMapper)in favor ofJsonLineMapper(JsonObjectUnmarshaller), see theJsonLineMapperagnostic to the JSON library section for more details. Scheduled for removal in version 7.0 -
Deprecate
JobRepository#getJobInstanceCount(String),JobExplorer#getJobInstanceCount(String), andJobInstanceDao#getJobInstanceCount(String)in favor ofcountJobInstances(String), andJobRepository#getStepExecutionCount(JobInstance, String)andJobExplorer#getStepExecutionCount(JobInstance, String)in favor ofcountStepExecutions(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