From d469ae459d930b81ad7596a609445b9650b164b5 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Thu, 20 Mar 2025 11:57:10 +0100 Subject: [PATCH 001/182] Update development version to 6.0.0-SNAPSHOT --- pom.xml | 2 +- spring-batch-bom/pom.xml | 2 +- spring-batch-core/pom.xml | 2 +- spring-batch-docs/pom.xml | 2 +- spring-batch-infrastructure/pom.xml | 2 +- spring-batch-integration/pom.xml | 2 +- spring-batch-samples/pom.xml | 2 +- spring-batch-test/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 659bcfc6b9..b059a18b08 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ designed to enable the development of robust batch applications vital for the daily operations of enterprise systems. Spring Batch is part of the Spring Portfolio. - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT pom https://projects.spring.io/spring-batch diff --git a/spring-batch-bom/pom.xml b/spring-batch-bom/pom.xml index b84343786e..a833c69e25 100644 --- a/spring-batch-bom/pom.xml +++ b/spring-batch-bom/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-bom pom diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml index 2118204831..01007a8d98 100644 --- a/spring-batch-core/pom.xml +++ b/spring-batch-core/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-core jar diff --git a/spring-batch-docs/pom.xml b/spring-batch-docs/pom.xml index 894f40a577..ca986a25fb 100644 --- a/spring-batch-docs/pom.xml +++ b/spring-batch-docs/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-docs Spring Batch Docs diff --git a/spring-batch-infrastructure/pom.xml b/spring-batch-infrastructure/pom.xml index d58993fc7f..71401f0fdd 100644 --- a/spring-batch-infrastructure/pom.xml +++ b/spring-batch-infrastructure/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-infrastructure jar diff --git a/spring-batch-integration/pom.xml b/spring-batch-integration/pom.xml index 6e7c8786bd..145357f0cd 100644 --- a/spring-batch-integration/pom.xml +++ b/spring-batch-integration/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-integration Spring Batch Integration diff --git a/spring-batch-samples/pom.xml b/spring-batch-samples/pom.xml index 036ca0d809..7196aa21b9 100644 --- a/spring-batch-samples/pom.xml +++ b/spring-batch-samples/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-samples jar diff --git a/spring-batch-test/pom.xml b/spring-batch-test/pom.xml index 3db3eeb42f..2320743f8d 100644 --- a/spring-batch-test/pom.xml +++ b/spring-batch-test/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch - 5.2.3-SNAPSHOT + 6.0.0-SNAPSHOT spring-batch-test Spring Batch Test From 2bd5b840643943bd6827b10e6092e93cbb73d1d9 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Fri, 21 Mar 2025 11:18:50 +0100 Subject: [PATCH 002/182] Update dependencies to next major versions snapshots --- pom.xml | 28 +++++++++---------- .../test/resources/META-INF/persistence.xml | 10 ++++--- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index b059a18b08..e3be833083 100644 --- a/pom.xml +++ b/pom.xml @@ -61,29 +61,29 @@ 17 - 6.2.4 - 2.0.11 - 6.4.3 - 1.14.5 + 7.0.0-SNAPSHOT + 2.0.12-SNAPSHOT + 6.5.0-SNAPSHOT + 1.15.0-SNAPSHOT - 3.4.4 - 3.4.4 - 3.4.4 - 4.4.4 - 3.3.4 - 3.2.4 - 3.2.11 + 4.0.0-SNAPSHOT + 4.0.0-SNAPSHOT + 4.0.0-SNAPSHOT + 5.0.0-SNAPSHOT + 4.0.0-SNAPSHOT + 4.0.0-SNAPSHOT + 3.3.0-SNAPSHOT 2.18.3 1.12.0 2.12.1 - 6.6.11.Final + 7.0.0.Beta4 3.0.0 2.1.3 3.1.0 3.1.1 - 3.1.0 + 3.2.0 4.0.16 5.3.1 5.11.4 @@ -92,7 +92,7 @@ 3.0.2 - 1.4.4 + 1.5.0-SNAPSHOT 1.4.21 4.13.2 diff --git a/spring-batch-infrastructure/src/test/resources/META-INF/persistence.xml b/spring-batch-infrastructure/src/test/resources/META-INF/persistence.xml index bb489174a6..70ac3d9ca0 100644 --- a/spring-batch-infrastructure/src/test/resources/META-INF/persistence.xml +++ b/spring-batch-infrastructure/src/test/resources/META-INF/persistence.xml @@ -1,13 +1,15 @@ - + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" + version="2.1"> org.springframework.batch.item.sample.Foo true - + + org/springframework/batch/item/database/Foo.hbm.xml + From 9d38aceade3fe1cb28caadbad233707c5f2b0b5c Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Tue, 29 Apr 2025 08:25:30 +0200 Subject: [PATCH 003/182] Update JUnit Jupiter to version 5.12.2 --- pom.xml | 3 ++- spring-batch-core/pom.xml | 6 ++++++ spring-batch-infrastructure/pom.xml | 6 +++--- spring-batch-integration/pom.xml | 6 ++++++ spring-batch-test/pom.xml | 6 ++++++ 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index e3be833083..b259171a3c 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,8 @@ 3.2.0 4.0.16 5.3.1 - 5.11.4 + 5.12.2 + 1.12.2 3.0.2 diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml index 01007a8d98..ae505b3dad 100644 --- a/spring-batch-core/pom.xml +++ b/spring-batch-core/pom.xml @@ -155,6 +155,12 @@ ${testcontainers.version} test + + org.junit.platform + junit-platform-launcher + ${junit-platform-launcher.version} + test + org.hsqldb hsqldb diff --git a/spring-batch-infrastructure/pom.xml b/spring-batch-infrastructure/pom.xml index 71401f0fdd..e305e63536 100644 --- a/spring-batch-infrastructure/pom.xml +++ b/spring-batch-infrastructure/pom.xml @@ -264,9 +264,9 @@ test - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} + org.junit.platform + junit-platform-launcher + ${junit-platform-launcher.version} test diff --git a/spring-batch-integration/pom.xml b/spring-batch-integration/pom.xml index 145357f0cd..fa06f58bce 100644 --- a/spring-batch-integration/pom.xml +++ b/spring-batch-integration/pom.xml @@ -150,6 +150,12 @@ ${junit-jupiter.version} test + + org.junit.platform + junit-platform-launcher + ${junit-platform-launcher.version} + test + org.slf4j slf4j-simple diff --git a/spring-batch-test/pom.xml b/spring-batch-test/pom.xml index 2320743f8d..30ca92fe41 100644 --- a/spring-batch-test/pom.xml +++ b/spring-batch-test/pom.xml @@ -79,6 +79,12 @@ ${junit-vintage-engine.version} test + + org.junit.platform + junit-platform-launcher + ${junit-platform-launcher.version} + test + org.mockito mockito-core From 43ac1f12cfd651abe68a94c3fdde235e3ca5135f Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Tue, 29 Apr 2025 08:57:30 +0200 Subject: [PATCH 004/182] Remove deprecated APIs scheduled for removal in v6 Resolves #4819 --- .../annotation/BatchRegistrar.java | 10 - .../annotation/EnableBatchProcessing.java | 10 +- .../support/DefaultBatchConfiguration.java | 63 +- .../support/JobRegistryBeanPostProcessor.java | 176 --- ...JobRegistrySmartInitializingSingleton.java | 5 +- .../xml/JobRepositoryParser.java | 7 +- .../xml/StepParserStepFactoryBean.java | 20 +- .../support/JobExplorerFactoryBean.java | 18 +- .../batch/core/job/builder/JobBuilder.java | 12 +- .../core/job/builder/JobBuilderHelper.java | 27 +- .../core/listener/ChunkListenerSupport.java | 43 - .../listener/JobExecutionListenerSupport.java | 37 - .../core/listener/SkipListenerSupport.java | 43 - .../StepExecutionListenerSupport.java | 41 - .../dao/JdbcExecutionContextDao.java | 19 +- .../repository/dao/JdbcJobInstanceDao.java | 13 +- .../support/JobRepositoryFactoryBean.java | 27 +- .../builder/AbstractTaskletStepBuilder.java | 29 +- .../batch/core/step/builder/StepBuilder.java | 67 +- .../core/step/builder/StepBuilderHelper.java | 25 +- .../core/step/builder/TaskletStepBuilder.java | 14 +- .../step/factory/SimpleStepFactoryBean.java | 18 +- .../configuration/xml/spring-batch-5.0.xsd | 1368 +++++++++++++++++ .../core/configuration/xml/spring-batch.xsd | 26 +- .../JobRegistryBeanPostProcessorTests.java | 125 -- .../xml/StepParserStepFactoryBeanTests.java | 5 +- .../configuration/xml/StepParserTests.java | 4 +- .../JobRepositoryFactoryBeanTests.java | 46 +- .../core/step/builder/StepBuilderTests.java | 7 +- .../step/item/SimpleStepFactoryBeanTests.java | 3 +- ...syncChunkOrientedStepIntegrationTests.java | 3 +- .../step/tasklet/AsyncTaskletStepTests.java | 3 +- .../JobRegistryIntegrationTests-context.xml | 2 +- .../configuration/support/test-context.xml | 2 +- .../support/trivial-context-autoregister.xml | 2 +- .../xml/JobRegistryJobParserTests-context.xml | 2 +- .../xml/JobRepositoryParserTests-context.xml | 3 +- ...epParserTaskletAttributesTests-context.xml | 2 +- ...tStepAllowStartIfCompleteTests-context.xml | 2 +- .../launch/support/launcher-with-locator.xml | 2 +- ...onment-with-registry-and-auto-register.xml | 2 +- .../resources/simple-job-launcher-context.xml | 2 +- .../modules/ROOT/pages/appendix.adoc | 10 +- .../ROOT/pages/job/advanced-meta-data.adoc | 54 +- .../item-reader-writer-implementations.adoc | 31 +- .../modules/ROOT/pages/scalability.adoc | 23 - .../batch/item/data/MongoItemReader.java | 266 ---- .../batch/item/data/MongoItemWriter.java | 15 +- .../item/data/MongoPagingItemReader.java | 187 ++- .../batch/item/data/Neo4jItemReader.java | 217 --- .../batch/item/data/Neo4jItemWriter.java | 126 -- .../data/builder/MongoItemReaderBuilder.java | 299 ---- .../data/builder/MongoItemWriterBuilder.java | 19 +- .../builder/MongoPagingItemReaderBuilder.java | 34 +- .../data/builder/Neo4jItemReaderBuilder.java | 265 ---- .../data/builder/Neo4jItemWriterBuilder.java | 81 - .../database/support/SqlPagingQueryUtils.java | 60 +- .../SqlWindowingPagingQueryProvider.java | 130 -- .../listener/RepeatListenerSupport.java | 53 - .../support/TaskExecutorRepeatTemplate.java | 21 +- .../support/SystemPropertyInitializer.java | 71 - .../batch/item/data/MongoItemWriterTests.java | 10 +- .../batch/item/data/Neo4jItemReaderTests.java | 171 --- .../batch/item/data/Neo4jItemWriterTests.java | 115 -- .../builder/MongoItemWriterBuilderTests.java | 6 +- .../builder/Neo4jItemReaderBuilderTests.java | 258 ---- .../builder/Neo4jItemWriterBuilderTests.java | 91 -- .../SqlWindowingPagingQueryProviderTests.java | 77 - ...ecutorRepeatTemplateAsynchronousTests.java | 3 +- ...orRepeatTemplateBulkAsynchronousTests.java | 104 +- .../TaskExecutorRepeatTemplateTests.java | 13 +- .../SystemPropertyInitializerTests.java | 62 - .../RemoteChunkingManagerStepBuilder.java | 28 +- .../RemotePartitioningManagerStepBuilder.java | 28 +- .../RemotePartitioningWorkerStepBuilder.java | 49 +- spring-batch-samples/README.md | 2 +- .../main/resources/data-source-context.xml | 1 - .../misc/jmx/adhoc-job-launcher-context.xml | 4 +- .../resources/simple-job-launcher-context.xml | 4 +- 79 files changed, 1632 insertions(+), 3691 deletions(-) delete mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java delete mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/listener/ChunkListenerSupport.java delete mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java delete mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java delete mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java create mode 100644 spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-5.0.xsd delete mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessorTests.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java delete mode 100644 spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java delete mode 100644 spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java index 3d23f6bcf7..073ef836d9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java @@ -111,11 +111,6 @@ private void registerJobRepository(BeanDefinitionRegistry registry, EnableBatchP beanDefinitionBuilder.addPropertyReference("serializer", executionContextSerializerRef); } - String lobHandlerRef = batchAnnotation.lobHandlerRef(); - if (registry.containsBeanDefinition(lobHandlerRef)) { - beanDefinitionBuilder.addPropertyReference("lobHandler", lobHandlerRef); - } - String conversionServiceRef = batchAnnotation.conversionServiceRef(); if (registry.containsBeanDefinition(conversionServiceRef)) { beanDefinitionBuilder.addPropertyReference("conversionService", conversionServiceRef); @@ -178,11 +173,6 @@ private void registerJobExplorer(BeanDefinitionRegistry registry, EnableBatchPro beanDefinitionBuilder.addPropertyReference("serializer", executionContextSerializerRef); } - String lobHandlerRef = batchAnnotation.lobHandlerRef(); - if (registry.containsBeanDefinition(lobHandlerRef)) { - beanDefinitionBuilder.addPropertyReference("lobHandler", lobHandlerRef); - } - String conversionServiceRef = batchAnnotation.conversionServiceRef(); if (registry.containsBeanDefinition(conversionServiceRef)) { beanDefinitionBuilder.addPropertyReference("conversionService", conversionServiceRef); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java index 27239d36c0..6e2740079d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -238,14 +238,6 @@ */ String jobKeyGeneratorRef() default "jobKeyGenerator"; - /** - * The large object handler to use in job repository and job explorer. - * @return the bean name of the lob handler to use. Defaults to {@literal lobHandler}. - * @deprecated Since 5.2 with no replacement. Scheduled for removal in v6 - */ - @Deprecated(since = "5.2.0", forRemoval = true) - String lobHandlerRef() default "lobHandler"; - /** * The type of large objects. * @return the type of large objects. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java index 67df9fd41f..484809fb2e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,8 +67,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.MetaDataAccessException; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; @@ -85,7 +83,8 @@ *
  • a {@link JobLauncher} named "jobLauncher"
  • *
  • a {@link JobRegistry} named "jobRegistry"
  • *
  • a {@link JobOperator} named "JobOperator"
  • - *
  • a {@link JobRegistryBeanPostProcessor} named "jobRegistryBeanPostProcessor"
  • + *
  • a {@link JobRegistrySmartInitializingSingleton} named + * "jobRegistrySmartInitializingSingleton"
  • *
  • a {@link org.springframework.batch.core.scope.StepScope} named "stepScope"
  • *
  • a {@link org.springframework.batch.core.scope.JobScope} named "jobScope"
  • * @@ -137,7 +136,6 @@ public JobRepository jobRepository() throws BatchConfigurationException { jobRepositoryFactoryBean.setSerializer(getExecutionContextSerializer()); jobRepositoryFactoryBean.setConversionService(getConversionService()); jobRepositoryFactoryBean.setJdbcOperations(getJdbcOperations()); - jobRepositoryFactoryBean.setLobHandler(getLobHandler()); jobRepositoryFactoryBean.setCharset(getCharset()); jobRepositoryFactoryBean.setMaxVarCharLength(getMaxVarCharLength()); jobRepositoryFactoryBean.setIsolationLevelForCreateEnum(getIsolationLevelForCreate()); @@ -150,17 +148,6 @@ public JobRepository jobRepository() throws BatchConfigurationException { } } - /** - * Define a job launcher. - * @return a job launcher - * @throws BatchConfigurationException if unable to configure the default job launcher - * @deprecated Since 5.2. Use {@link #jobLauncher(JobRepository)} instead - */ - @Deprecated(forRemoval = true) - public JobLauncher jobLauncher() throws BatchConfigurationException { - return jobLauncher(jobRepository()); - } - /** * Define a job launcher bean. * @param jobRepository the job repository @@ -191,7 +178,6 @@ public JobExplorer jobExplorer() throws BatchConfigurationException { jobExplorerFactoryBean.setJobKeyGenerator(getJobKeyGenerator()); jobExplorerFactoryBean.setCharset(getCharset()); jobExplorerFactoryBean.setTablePrefix(getTablePrefix()); - jobExplorerFactoryBean.setLobHandler(getLobHandler()); jobExplorerFactoryBean.setConversionService(getConversionService()); jobExplorerFactoryBean.setSerializer(getExecutionContextSerializer()); try { @@ -208,18 +194,6 @@ public JobRegistry jobRegistry() throws BatchConfigurationException { return new MapJobRegistry(); } - /** - * Define a job operator. - * @return a job operator - * @throws BatchConfigurationException if unable to configure the default job operator - * @deprecated Since 5.2. Use - * {@link #jobOperator(JobRepository, JobExplorer, JobRegistry, JobLauncher)} instead - */ - @Deprecated(forRemoval = true) - public JobOperator jobOperator() throws BatchConfigurationException { - return jobOperator(jobRepository(), jobExplorer(), jobRegistry(), jobLauncher()); - } - /** * Define a job operator bean. * @param jobRepository a job repository @@ -249,26 +223,6 @@ public JobOperator jobOperator(JobRepository jobRepository, JobExplorer jobExplo } } - /** - * Defines a {@link JobRegistryBeanPostProcessor}. - * @return a {@link JobRegistryBeanPostProcessor} - * @throws BatchConfigurationException if unable to register the bean - * @since 5.1 - * @deprecated Use {@link #jobRegistrySmartInitializingSingleton(JobRegistry)} instead - */ - @Deprecated(forRemoval = true) - public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() throws BatchConfigurationException { - JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor(); - jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry()); - try { - jobRegistryBeanPostProcessor.afterPropertiesSet(); - return jobRegistryBeanPostProcessor; - } - catch (Exception e) { - throw new BatchConfigurationException("Unable to configure the default job registry BeanPostProcessor", e); - } - } - /** * Define a {@link JobRegistrySmartInitializingSingleton} bean. * @param jobRegistry the job registry to populate @@ -388,17 +342,6 @@ protected Charset getCharset() { return StandardCharsets.UTF_8; } - /** - * A special handler for large objects. The default is usually fine, except for some - * (usually older) versions of Oracle. - * @return the {@link LobHandler} to use - * @deprecated Since 5.2 with no replacement. Scheduled for removal in v6 - */ - @Deprecated(since = "5.2.0", forRemoval = true) - protected LobHandler getLobHandler() { - return new DefaultLobHandler(); - } - /** * Return the {@link JdbcOperations}. If this property is not overridden, a new * {@link JdbcTemplate} will be created for the configured data source by default. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java deleted file mode 100644 index 1f6ba7acfa..0000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2006-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.support; - -import java.util.Collection; -import java.util.HashSet; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.configuration.DuplicateJobException; -import org.springframework.batch.core.configuration.JobLocator; -import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.beans.BeansException; -import org.springframework.beans.FatalBeanException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.util.Assert; - -/** - * A {@link BeanPostProcessor} that registers {@link Job} beans with a - * {@link JobRegistry}. Include a bean of this type along with your job configuration and - * use the same {@link JobRegistry} as a {@link JobLocator} when you need to locate a - * {@link Job} to launch. - *

    - * An alternative to this class is {@link JobRegistrySmartInitializingSingleton}, which is - * recommended in cases where this class may cause early bean initializations. You must - * include at most one of either of them as a bean. - * - * @deprecated since 5.2 in favor of {@link JobRegistrySmartInitializingSingleton}. - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -@Deprecated(since = "5.2") -public class JobRegistryBeanPostProcessor - implements BeanPostProcessor, BeanFactoryAware, InitializingBean, DisposableBean { - - private static final Log logger = LogFactory.getLog(JobRegistryBeanPostProcessor.class); - - // It doesn't make sense for this to have a default value... - private JobRegistry jobRegistry = null; - - private final Collection jobNames = new HashSet<>(); - - private String groupName = null; - - private DefaultListableBeanFactory beanFactory; - - /** - * The group name for jobs registered by this component. Optional (defaults to null, - * which means that jobs are registered with their bean names). Useful where there is - * a hierarchy of application contexts all contributing to the same - * {@link JobRegistry}: child contexts can then define an instance with a unique group - * name to avoid clashes between job names. - * @param groupName the groupName to set - */ - public void setGroupName(String groupName) { - this.groupName = groupName; - } - - /** - * Injection setter for {@link JobRegistry}. - * @param jobRegistry the jobConfigurationRegistry to set - */ - public void setJobRegistry(JobRegistry jobRegistry) { - this.jobRegistry = jobRegistry; - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - if (beanFactory instanceof DefaultListableBeanFactory) { - this.beanFactory = (DefaultListableBeanFactory) beanFactory; - } - } - - /** - * Make sure the registry is set before use. - * - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(jobRegistry != null, "JobRegistry must not be null"); - } - - /** - * Unregister all the {@link Job} instances that were registered by this post - * processor. - * @see org.springframework.beans.factory.DisposableBean#destroy() - */ - @Override - public void destroy() throws Exception { - for (String name : jobNames) { - if (logger.isDebugEnabled()) { - logger.debug("Unregistering job: " + name); - } - jobRegistry.unregister(name); - } - jobNames.clear(); - } - - /** - * If the bean is an instance of {@link Job}, then register it. - * @throws FatalBeanException if there is a {@link DuplicateJobException}. - * - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, - * java.lang.String) - */ - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof Job job) { - try { - String groupName = this.groupName; - if (beanFactory != null && beanFactory.containsBean(beanName)) { - groupName = getGroupName(beanFactory.getBeanDefinition(beanName), job); - } - job = groupName == null ? job : new GroupAwareJob(groupName, job); - ReferenceJobFactory jobFactory = new ReferenceJobFactory(job); - String name = jobFactory.getJobName(); - if (logger.isDebugEnabled()) { - logger.debug("Registering job: " + name); - } - jobRegistry.register(jobFactory); - jobNames.add(name); - } - catch (DuplicateJobException e) { - throw new FatalBeanException("Cannot register job configuration", e); - } - return job; - } - return bean; - } - - /** - * Determine a group name for the job to be registered. The default implementation - * returns the {@link #setGroupName(String) groupName} configured. Provides an - * extension point for specialised subclasses. - * @param beanDefinition the bean definition for the job - * @param job the job - * @return a group name for the job (or null if not needed) - */ - protected String getGroupName(BeanDefinition beanDefinition, Job job) { - return groupName; - } - - /** - * Do nothing. - * - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, - * java.lang.String) - */ - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java index ede418cf23..bd6f5b9a44 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistrySmartInitializingSingleton.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 the original author or authors. + * Copyright 2024-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,9 +42,6 @@ * {@link JobRegistry}. Include a bean of this type along with your job configuration and * use the same {@link JobRegistry} as a {@link JobLocator} when you need to locate a * {@link Job} to launch. - *

    - * This class is an alternative to {@link JobRegistryBeanPostProcessor} and prevents early - * bean initializations. You must include at most one of either of them as a bean. * * @author Henning Pƶttker * @since 5.1.1 diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java index be88087562..bbe403a114 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,8 +77,6 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit String maxVarCharLength = element.getAttribute("max-varchar-length"); - String lobHandler = element.getAttribute("lob-handler"); - String serializer = element.getAttribute("serializer"); String conversionService = element.getAttribute("conversion-service"); @@ -97,9 +95,6 @@ protected void doParse(Element element, ParserContext parserContext, BeanDefinit if (StringUtils.hasText(tablePrefix)) { builder.addPropertyValue("tablePrefix", tablePrefix); } - if (StringUtils.hasText(lobHandler)) { - builder.addPropertyReference("lobHandler", lobHandler); - } if (StringUtils.hasText(maxVarCharLength)) { builder.addPropertyValue("maxVarCharLength", maxVarCharLength); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index 7b18458ee7..187bda9a31 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -185,8 +185,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN private TaskExecutor taskExecutor; - private Integer throttleLimit; - private ItemReader itemReader; private ItemProcessor itemProcessor; @@ -473,9 +471,6 @@ protected void enhanceTaskletStepBuilder(AbstractTaskletStepBuilder builder) } builder.taskExecutor(taskExecutor); - if (throttleLimit != null) { - builder.throttleLimit(throttleLimit); - } builder.transactionManager(transactionManager); if (transactionTimeout != null || propagation != null || isolation != null || noRollbackExceptionClasses != null) { @@ -992,19 +987,6 @@ public void setTaskExecutor(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } - /** - * Public setter for the throttle limit. This limits the number of tasks queued for - * concurrent processing to prevent thread pools from being overwhelmed. Defaults to - * {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. - * @param throttleLimit The throttle limit to set. - * @deprecated since 5.0, scheduled for removal in 6.0. This API is not intended for - * end users anyway. It is only used by the XML namespace parser. - */ - @Deprecated(since = "5.0", forRemoval = true) - public void setThrottleLimit(Integer throttleLimit) { - this.throttleLimit = throttleLimit; - } - /** * @param itemReader The {@link ItemReader} to set. */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java index 9d3e24dae5..49f5661e69 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.lang.NonNull; import org.springframework.util.Assert; @@ -81,8 +80,6 @@ protected long getNextKey() { private JobKeyGenerator jobKeyGenerator; - private LobHandler lobHandler; - private ExecutionContextSerializer serializer; private Charset charset = StandardCharsets.UTF_8; @@ -138,18 +135,6 @@ public void setJobKeyGenerator(JobKeyGenerator jobKeyGenerator) { this.jobKeyGenerator = jobKeyGenerator; } - /** - * The lob handler to use when saving {@link ExecutionContext} instances. Defaults to - * {@code null}, which works for most databases. - * @param lobHandler Large object handler for saving an - * {@link org.springframework.batch.item.ExecutionContext}. - * @deprecated Since 5.2 with no replacement. Scheduled for removal in v6 - */ - @Deprecated(since = "5.2.0", forRemoval = true) - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - /** * Sets the {@link Charset} to use when deserializing the execution context. Defaults * to "UTF-8". Must not be {@code null}. @@ -210,7 +195,6 @@ public void afterPropertiesSet() throws Exception { protected ExecutionContextDao createExecutionContextDao() throws Exception { JdbcExecutionContextDao dao = new JdbcExecutionContextDao(); dao.setJdbcTemplate(jdbcOperations); - dao.setLobHandler(lobHandler); dao.setTablePrefix(tablePrefix); dao.setSerializer(serializer); dao.setCharset(charset); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java index 6ea4823189..85f44a1a36 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,16 +30,6 @@ */ public class JobBuilder extends JobBuilderHelper { - /** - * Create a new builder for a job with the given name. - * @param name the name of the job - * @deprecated use {@link JobBuilder#JobBuilder(String, JobRepository)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public JobBuilder(String name) { - super(name); - } - /** * Create a new builder for a job with the given name. * @param name the name of the job diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java index cacf2eab6f..dee585863e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,17 +54,6 @@ public abstract class JobBuilderHelper> { private final CommonJobProperties properties; - /** - * Create a new {@link JobBuilderHelper}. - * @param name the job name - * @deprecated use {@link JobBuilderHelper#JobBuilderHelper(String, JobRepository)} - */ - @Deprecated(since = "5.1", forRemoval = true) - public JobBuilderHelper(String name) { - this.properties = new CommonJobProperties(); - properties.name = name; - } - /** * Create a new {@link JobBuilderHelper}. * @param name the job name @@ -110,20 +99,6 @@ public B incrementer(JobParametersIncrementer jobParametersIncrementer) { return result; } - /** - * Sets the job repository for the job. - * @param jobRepository the job repository (mandatory) - * @return this to enable fluent chaining - * @deprecated use {@link JobBuilderHelper#JobBuilderHelper(String, JobRepository)} - */ - @Deprecated(since = "5.1", forRemoval = true) - public B repository(JobRepository jobRepository) { - properties.jobRepository = jobRepository; - @SuppressWarnings("unchecked") - B result = (B) this; - return result; - } - /** * Sets the job observation convention. * @param observationConvention the job observation convention (optional) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ChunkListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ChunkListenerSupport.java deleted file mode 100644 index 79d742240e..0000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ChunkListenerSupport.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2006-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.springframework.batch.core.ChunkListener; -import org.springframework.batch.core.scope.context.ChunkContext; - -/** - * Basic support implementation of {@link ChunkListener} - * - * @author Lucas Ward - * @author Michael Minella - * @deprecated as of 5.0, in favor of the default methods on the {@link ChunkListener} - */ -@Deprecated -public class ChunkListenerSupport implements ChunkListener { - - @Override - public void afterChunk(ChunkContext context) { - } - - @Override - public void beforeChunk(ChunkContext context) { - } - - @Override - public void afterChunkError(ChunkContext context) { - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java deleted file mode 100644 index fe54e5a6b6..0000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2006-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobExecutionListener; - -/** - * @author Dave Syer - * @deprecated as of 5.0, in favor of the default methods on the - * {@link JobExecutionListener} - */ -@Deprecated -public class JobExecutionListenerSupport implements JobExecutionListener { - - @Override - public void afterJob(JobExecution jobExecution) { - } - - @Override - public void beforeJob(JobExecution jobExecution) { - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java deleted file mode 100644 index 00001e2ee3..0000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2006-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.springframework.batch.core.SkipListener; - -/** - * Basic no-op implementations of all {@link SkipListener} implementations. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @deprecated as of v5.0 in favor of the default methods in {@link SkipListener}. - * - */ -@Deprecated -public class SkipListenerSupport implements SkipListener { - - @Override - public void onSkipInRead(Throwable t) { - } - - @Override - public void onSkipInWrite(S item, Throwable t) { - } - - @Override - public void onSkipInProcess(T item, Throwable t) { - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java deleted file mode 100644 index bd4bedb07f..0000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2006-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.lang.Nullable; - -/** - * @author Dave Syer - * @deprecated as of 5.0, in favor of the default methods on the - * {@link StepExecutionListener} - */ -@Deprecated -public class StepExecutionListenerSupport implements StepExecutionListener { - - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - return null; - } - - @Override - public void beforeStep(StepExecution stepExecution) { - } - -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java index 07915965c0..47b8b40c1c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,6 @@ import org.springframework.core.serializer.Serializer; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.lang.NonNull; import org.springframework.util.Assert; @@ -110,8 +108,6 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem private int shortContextLength = DEFAULT_MAX_VARCHAR_LENGTH; - private LobHandler lobHandler = new DefaultLobHandler(); - private ExecutionContextSerializer serializer = new DefaultExecutionContextSerializer(); private final Lock lock = new ReentrantLock(); @@ -268,15 +264,6 @@ public void deleteExecutionContext(StepExecution stepExecution) { getJdbcTemplate().update(getQuery(DELETE_STEP_EXECUTION_CONTEXT), stepExecution.getId()); } - /** - * @deprecated Since 5.2 with no replacement. Scheduled for removal in v6 - * @param lobHandler the lob handler to use - */ - @Deprecated(since = "5.2.0", forRemoval = true) - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); @@ -306,7 +293,7 @@ private void persistSerializedContext(final Long executionId, String serializedC getJdbcTemplate().update(getQuery(sql), ps -> { ps.setString(1, shortContext); if (longContext != null) { - lobHandler.getLobCreator().setClobAsString(ps, 2, longContext); + ps.setString(2, longContext); } else { ps.setNull(2, getClobTypeToUse()); @@ -342,7 +329,7 @@ public void setValues(PreparedStatement ps, int i) throws SQLException { } ps.setString(1, shortContext); if (longContext != null) { - lobHandler.getLobCreator().setClobAsString(ps, 2, longContext); + ps.setString(2, longContext); } else { ps.setNull(2, getClobTypeToUse()); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java index 27dcc8b7a2..8b503899a9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -284,17 +284,6 @@ public void deleteJobInstance(JobInstance jobInstance) { getJdbcTemplate().update(getQuery(DELETE_JOB_INSTANCE), jobInstance.getId()); } - /** - * Setter for {@link DataFieldMaxValueIncrementer} to be used when generating primary - * keys for {@link JobInstance} instances. - * @param jobIncrementer the {@link DataFieldMaxValueIncrementer} - * @deprecated as of v5.0 in favor of using the {@link #setJobInstanceIncrementer} - */ - @Deprecated - public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) { - this.setJobInstanceIncrementer(jobIncrementer); - } - /** * Setter for {@link DataFieldMaxValueIncrementer} to be used when generating primary * keys for {@link JobInstance} instances. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java index 70b0b54436..ac2bd74b62 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,8 +56,6 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.lang.NonNull; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -95,8 +93,6 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i private int maxVarCharLengthForShortContext = AbstractJdbcBatchMetadataDao.DEFAULT_SHORT_CONTEXT_LENGTH; - private LobHandler lobHandler; - private ExecutionContextSerializer serializer; private Integer clobType; @@ -124,19 +120,6 @@ public void setSerializer(ExecutionContextSerializer serializer) { this.serializer = serializer; } - /** - * A special handler for large objects. The default is usually fine, except for some - * (usually older) versions of Oracle. The default is determined from the data base - * type. - * @param lobHandler the {@link LobHandler} to set - * @deprecated Since 5.2 with no replacement. Scheduled for removal in v6 - * @see LobHandler - */ - @Deprecated(since = "5.2.0", forRemoval = true) - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - /** * Public setter for the length of long string columns in database. Do not set this if * you haven't modified the schema. Note this value will be used for the exit message @@ -276,10 +259,6 @@ public void afterPropertiesSet() throws Exception { } } - if (lobHandler == null && databaseType.equalsIgnoreCase(DatabaseType.ORACLE.toString())) { - lobHandler = new DefaultLobHandler(); - } - if (serializer == null) { serializer = new DefaultExecutionContextSerializer(); } @@ -355,10 +334,6 @@ protected ExecutionContextDao createExecutionContextDao() throws Exception { dao.setSerializer(serializer); dao.setCharset(charset); - if (lobHandler != null) { - dao.setLobHandler(lobHandler); - } - dao.afterPropertiesSet(); dao.setShortContextLength(this.maxVarCharLengthForShortContext); return dao; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java index 55e6a0fdce..3a5eb7ab0f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,8 +67,6 @@ public abstract class AbstractTaskletStepBuilder parent) { @@ -88,7 +86,6 @@ public AbstractTaskletStepBuilder(AbstractTaskletStepBuilder parent) { this.transactionAttribute = parent.transactionAttribute; this.streams.addAll(parent.streams); this.exceptionHandler = parent.exceptionHandler; - this.throttleLimit = parent.throttleLimit; this.taskExecutor = parent.taskExecutor; } @@ -125,7 +122,6 @@ public TaskletStep build() { if (taskExecutor != null) { TaskExecutorRepeatTemplate repeatTemplate = new TaskExecutorRepeatTemplate(); repeatTemplate.setTaskExecutor(taskExecutor); - repeatTemplate.setThrottleLimit(throttleLimit); stepOperations = repeatTemplate; } @@ -210,24 +206,6 @@ public B taskExecutor(TaskExecutor taskExecutor) { return self(); } - /** - * In the case of an asynchronous {@link #taskExecutor(TaskExecutor)} the number of - * concurrent tasklet executions can be throttled (beyond any throttling provided by a - * thread pool). The throttle limit should be less than the data source pool size used - * in the job repository for this step. - * @param throttleLimit maximum number of concurrent tasklet executions allowed - * @return this for fluent chaining - * @deprecated with no replacement since 5.0, scheduled for removal in 6.0. Use a - * custom {@link RepeatOperations} implementation (based on a {@link TaskExecutor} - * with a bounded task queue) and set it on the step with - * {@link #stepOperations(RepeatOperations)}. - */ - @Deprecated(since = "5.0", forRemoval = true) - public B throttleLimit(int throttleLimit) { - this.throttleLimit = throttleLimit; - return self(); - } - /** * Sets the exception handler to use in the case of tasklet failures. Default is to * rethrow everything. @@ -302,11 +280,6 @@ protected TaskExecutor getTaskExecutor() { return taskExecutor; } - @Deprecated(since = "5.0", forRemoval = true) - protected int getThrottleLimit() { - return throttleLimit; - } - protected TransactionAttribute getTransactionAttribute() { return transactionAttribute; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java index 8d49029a7a..9ae5289a22 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,16 +34,6 @@ */ public class StepBuilder extends StepBuilderHelper { - /** - * Initialize a step builder for a step with the given name. - * @param name the name of the step - * @deprecated use {@link StepBuilder#StepBuilder(String, JobRepository)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public StepBuilder(String name) { - super(name); - } - /** * Initialize a step builder for a step with the given name and job repository. * @param name the name of the step @@ -54,17 +44,6 @@ public StepBuilder(String name, JobRepository jobRepository) { super(name, jobRepository); } - /** - * Build a step with a custom tasklet, not necessarily item processing. - * @param tasklet a tasklet - * @return a {@link TaskletStepBuilder} - * @deprecated use {@link StepBuilder#tasklet(Tasklet, PlatformTransactionManager)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public TaskletStepBuilder tasklet(Tasklet tasklet) { - return new TaskletStepBuilder(this).tasklet(tasklet); - } - /** * Build a step with a custom tasklet, not necessarily item processing. * @param tasklet a tasklet @@ -76,27 +55,6 @@ public TaskletStepBuilder tasklet(Tasklet tasklet, PlatformTransactionManager tr return new TaskletStepBuilder(this).tasklet(tasklet, transactionManager); } - /** - * Build a step that processes items in chunks with the size provided. To extend the - * step to being fault tolerant, call the {@link SimpleStepBuilder#faultTolerant()} - * method on the builder. In most cases you will want to parameterize your call to - * this method, to preserve the type safety of your readers and writers, e.g. - * - *

    -	 * new StepBuilder("step1").<Order, Ledger> chunk(100).reader(new OrderReader()).writer(new LedgerWriter())
    -	 * // ... etc.
    -	 * 
    - * @param chunkSize the chunk size (commit interval) - * @return a {@link SimpleStepBuilder} - * @param the type of item to be processed as input - * @param the type of item to be output - * @deprecated use {@link StepBuilder#chunk(int, PlatformTransactionManager)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public SimpleStepBuilder chunk(int chunkSize) { - return new SimpleStepBuilder(this).chunk(chunkSize); - } - /** * Build a step that processes items in chunks with the size provided. To extend the * step to being fault tolerant, call the {@link SimpleStepBuilder#faultTolerant()} @@ -119,29 +77,6 @@ public SimpleStepBuilder chunk(int chunkSize, PlatformTransactionMa return new SimpleStepBuilder(this).transactionManager(transactionManager).chunk(chunkSize); } - /** - * Build a step that processes items in chunks with the completion policy provided. To - * extend the step to being fault tolerant, call the - * {@link SimpleStepBuilder#faultTolerant()} method on the builder. In most cases you - * will want to parameterize your call to this method, to preserve the type safety of - * your readers and writers, e.g. - * - *
    -	 * new StepBuilder("step1").<Order, Ledger> chunk(100).reader(new OrderReader()).writer(new LedgerWriter())
    -	 * // ... etc.
    -	 * 
    - * @param completionPolicy the completion policy to use to control chunk processing - * @return a {@link SimpleStepBuilder} - * @param the type of item to be processed as input - * @param the type of item to be output - * @deprecated use - * {@link StepBuilder#chunk(CompletionPolicy, PlatformTransactionManager)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public SimpleStepBuilder chunk(CompletionPolicy completionPolicy) { - return new SimpleStepBuilder(this).chunk(completionPolicy); - } - /** * Build a step that processes items in chunks with the completion policy provided. To * extend the step to being fault tolerant, call the diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java index 577f383e08..802325a30f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,17 +53,6 @@ public abstract class StepBuilderHelper> { protected final CommonStepProperties properties; - /** - * Create a new {@link StepBuilderHelper}. - * @param name the step name - * @deprecated use {@link StepBuilderHelper#StepBuilderHelper(String, JobRepository)} - */ - @Deprecated(since = "5.1", forRemoval = true) - public StepBuilderHelper(String name) { - this.properties = new CommonStepProperties(); - properties.name = name; - } - /** * Create a new {@link StepBuilderHelper}. * @param name the step name @@ -85,18 +74,6 @@ protected StepBuilderHelper(StepBuilderHelper parent) { this.properties = new CommonStepProperties(parent.properties); } - /** - * Set the job repository - * @param jobRepository the repository to set - * @return this to enable fluent chaining - * @deprecated use {@link StepBuilderHelper#StepBuilderHelper(String, JobRepository)} - */ - @Deprecated(since = "5.1", forRemoval = true) - public B repository(JobRepository jobRepository) { - properties.jobRepository = jobRepository; - return self(); - } - /** * Sets the step observation convention. * @param observationConvention the step observation convention (optional) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java index bf4aad229f..896fce2cea 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,18 +38,6 @@ public TaskletStepBuilder(StepBuilderHelper parent) { super(parent); } - /** - * @param tasklet the tasklet to use - * @return this for fluent chaining - * @deprecated use - * {@link TaskletStepBuilder#tasklet(Tasklet, PlatformTransactionManager)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public TaskletStepBuilder tasklet(Tasklet tasklet) { - this.tasklet = tasklet; - return this; - } - /** * @param tasklet the tasklet to use * @return this for fluent chaining diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java index 5acb2a4d93..d2d672676a 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -441,20 +441,6 @@ protected TaskExecutor getTaskExecutor() { return taskExecutor; } - /** - * Public setter for the throttle limit. This limits the number of tasks queued for - * concurrent processing to prevent thread pools from being overwhelmed. Defaults to - * {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. - * @param throttleLimit the throttle limit to set. - * @deprecated since 5.0, scheduled for removal in 6.0. Use a pooled - * {@link TaskExecutor} implementation with a limited capacity of its task queue - * instead. - */ - @Deprecated(since = "5.0", forRemoval = true) - public void setThrottleLimit(int throttleLimit) { - this.throttleLimit = throttleLimit; - } - protected void applyConfiguration(SimpleStepBuilder builder) { builder.reader(itemReader); @@ -482,7 +468,6 @@ protected void applyConfiguration(SimpleStepBuilder builder) { } builder.transactionManager(transactionManager); builder.transactionAttribute(getTransactionAttribute()); - builder.repository(jobRepository); builder.observationRegistry(observationRegistry); builder.startLimit(startLimit); builder.allowStartIfComplete(allowStartIfComplete); @@ -491,7 +476,6 @@ protected void applyConfiguration(SimpleStepBuilder builder) { builder.chunkOperations(chunkOperations); builder.stepOperations(stepOperations); builder.taskExecutor(taskExecutor); - builder.throttleLimit(throttleLimit); builder.exceptionHandler(exceptionHandler); if (isReaderTransactionalQueue) { builder.readerIsTransactionalQueue(); diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-5.0.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-5.0.xsd new file mode 100644 index 0000000000..1c5b20f37c --- /dev/null +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-5.0.xsd @@ -0,0 +1,1368 @@ + + + + + + + + + + + + + + Defines a job composed of a set of steps and + transitions between steps. The job will be exposed in + the enclosing + bean factory as a component of type Job + that can be launched using a + JobLauncher. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a stage in job processing backed by a + Step. The id attribute must be specified since this + step definition + will be referred to from other elements + to form a Job flow. + + + + + + + + + + + + + + + + + Defines a flow composed of a set of steps and + transitions between steps. + + + + + + + + + + + + + + + + + + A reference to a JobExecutionListener (or a POJO + if using before-job-method / after-job-method or + source level + annotations). + + + + + + + + + + + + + + + A bean definition for a step listener (or POJO if + using *-method attributes or source level + annotations) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a stage in job processing backed by a + Step. The id attribute must be specified. The + step + requires either + a chunk definition, + a tasklet reference, or a reference to a + (possibly abstract) parent step. + + + + + + + + + + + + + + + + Declares job should split here into two or more + subflows. + + + + + + + + A subflow within a job, having the same + format as a job, but without a separate identity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Declares job should include an externalized flow + here. + + + + + + + + + + + + + + + + + + + + + + Declares job should query a decider to determine + where execution should go next. + + + + + + + + + The decider is a reference to a + JobExecutionDecider that can produce a status to base + the next + transition on. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The tasklet is a reference to another bean + definition that implements + the Tasklet interface. + + + + + + + + + + If the tasklet is specified as a bean definition, then a method can be specified and a POJO + will + be adapted to the Tasklet interface. The method suggested should have the same arguments + as Tasklet.execute (or a subset), and have a compatible return type (boolean, void or RepeatStatus). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + An exception class name. + + + + + + + + + + + + + + + + + Classify an exception as "included" in the set. Exceptions of this type or a subclass are + included. + + + + + + + + + + + + + + + + Classify an exception as "excluded" from the + set. Exceptions of this type or a subclass are + excluded + + + + + + + + + + + + + + + A reference to a listener, a POJO with a + listener-annotated method, or a POJO with + a method + referenced by a + *-method attribute. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a transition from this step to the + next + one depending on the value of the exit + status. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. When a + step finishes + the most + specific match will be chosen to select the next step. + Hint: + always include a default + transition with on="*". + + + + + + + The name of the step to go to next. Must + resolve to one of the other steps in this job. + + + + + + + + + Declares job should be stop at this point and + provides pointer where execution should continue + when + the job is + restarted. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The name of the step to start on when the + stopped job is restarted. + Must resolve to one of the + other steps + in this job. + + + + + + The exit code value to end on, defaults to + STOPPED. + + + + + + + + Declares job should end at this point, without + the possibility of restart. + BatchStatus will be + COMPLETED. + ExitStatus is configurable. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The exit code value to end on, defaults to + COMPLETED. + + + + + + + + Declares job should fail at this point. + BatchStatus will be FAILED. ExitStatus is configurable. + + + + + + A pattern to match against the exit status + code. Use * and ? as wildcard characters. + When a step + finishes + the most specific match will be chosen to + select the next step. + + + + + + The exit code value to end on, defaults to + FAILED. + + + + + + + + + + + + + + + + + + + + + + + + + The name of the parent bean from which the + configuration should inherit. + + + + + + + + + + + + + Is this bean "abstract", that is, not meant to be + instantiated itself + but rather just serving as + parent for concrete + child bean definitions? + The default is "false". Specify "true" to + tell the bean factory to not + try + to instantiate that particular bean + in any case. + + Note: This attribute will not be inherited by child + bean definitions. + Hence, it needs to be specified per abstract bean + definition. + + + + + + + + + + Should this list be merged with the corresponding + list provided + by the parent? If not, it will + overwrite the parent + list. + + + + + + + + + + This attribute indicates the method from the + class that should + be used to dynamically create a + proxy. + + + + + + + + + + + + + diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch.xsd index 1c5b20f37c..7656c45854 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch.xsd @@ -6,7 +6,7 @@ xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tool https://www.springframework.org/schema/tool/spring-tool.xsd" - version="5.0"> + version="6.0"> @@ -265,20 +265,6 @@ - - - - - - - - - - - - - - - diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessorTests.java deleted file mode 100644 index a7913ed0b9..0000000000 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessorTests.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2006-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.support; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Collection; - -import org.junit.jupiter.api.Test; -import org.springframework.batch.core.configuration.DuplicateJobException; -import org.springframework.batch.core.job.JobSupport; -import org.springframework.beans.FatalBeanException; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -class JobRegistryBeanPostProcessorTests { - - private final JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor(); - - @Test - void testInitializationFails() { - Exception exception = assertThrows(IllegalStateException.class, processor::afterPropertiesSet); - assertTrue(exception.getMessage().contains("JobRegistry")); - } - - @Test - void testBeforeInitialization() { - // should be a no-op - assertEquals("foo", processor.postProcessBeforeInitialization("foo", "bar")); - } - - @Test - void testAfterInitializationWithWrongType() { - // should be a no-op - assertEquals("foo", processor.postProcessAfterInitialization("foo", "bar")); - } - - @Test - void testAfterInitializationWithCorrectType() { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport job = new JobSupport(); - job.setBeanName("foo"); - assertNotNull(processor.postProcessAfterInitialization(job, "bar")); - assertEquals("[foo]", registry.getJobNames().toString()); - } - - @Test - void testAfterInitializationWithGroupName() { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - processor.setGroupName("jobs"); - JobSupport job = new JobSupport(); - job.setBeanName("foo"); - assertNotNull(processor.postProcessAfterInitialization(job, "bar")); - assertEquals("[jobs.foo]", registry.getJobNames().toString()); - } - - @Test - void testAfterInitializationWithDuplicate() { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport job = new JobSupport(); - job.setBeanName("foo"); - processor.postProcessAfterInitialization(job, "bar"); - Exception exception = assertThrows(FatalBeanException.class, - () -> processor.postProcessAfterInitialization(job, "spam")); - assertTrue(exception.getCause() instanceof DuplicateJobException); - } - - @Test - void testUnregisterOnDestroy() throws Exception { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport job = new JobSupport(); - job.setBeanName("foo"); - assertNotNull(processor.postProcessAfterInitialization(job, "bar")); - processor.destroy(); - assertEquals("[]", registry.getJobNames().toString()); - } - - @Test - void testExecutionWithApplicationContext() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test-context.xml", getClass()); - MapJobRegistry registry = (MapJobRegistry) context.getBean("registry"); - Collection configurations = registry.getJobNames(); - String[] names = context.getBeanNamesForType(JobSupport.class); - int count = names.length; - // Each concrete bean of type JobConfiguration is registered... - assertEquals(count, configurations.size()); - // N.B. there is a failure / wonky mode where a parent bean is given an - // explicit name or beanName (using property setter): in this case then - // child beans will have the same name and will be re-registered (and - // override, if the registry supports that). - assertNotNull(registry.getJob("test-job")); - assertEquals(context.getBean("test-job-with-name"), registry.getJob("foo")); - assertEquals(context.getBean("test-job-with-bean-name"), registry.getJob("bar")); - assertEquals(context.getBean("test-job-with-parent-and-name"), registry.getJob("spam")); - assertEquals(context.getBean("test-job-with-parent-and-bean-name"), registry.getJob("bucket")); - assertEquals(context.getBean("test-job-with-concrete-parent"), registry.getJob("maps")); - assertEquals(context.getBean("test-job-with-concrete-parent-and-name"), registry.getJob("oof")); - assertEquals(context.getBean("test-job-with-concrete-parent-and-bean-name"), registry.getJob("rab")); - } - -} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java index 37949ce5fd..91f4963ead 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -239,7 +239,6 @@ void testFaultTolerantStep() throws Exception { fb.setIsReaderTransactionalQueue(true); fb.setRetryLimit(5); fb.setSkipLimit(100); - fb.setThrottleLimit(10); fb.setRetryListeners(new RetryListener() { }); @SuppressWarnings("unchecked") @@ -251,7 +250,7 @@ void testFaultTolerantStep() throws Exception { assertTrue(step instanceof TaskletStep); Object throttleLimit = ReflectionTestUtils.getField(ReflectionTestUtils.getField(step, "stepOperations"), "throttleLimit"); - assertEquals(10, throttleLimit); + assertEquals(4, throttleLimit); Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); assertTrue(tasklet instanceof ChunkOrientedTasklet); assertFalse((Boolean) ReflectionTestUtils.getField(tasklet, "buffering")); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java index 541e402264..7d709d6ef8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,8 +88,6 @@ void testTaskletStepAttributes() throws Exception { StepParserStepFactoryBean factory = beans.get(factoryName); TaskletStep bean = (TaskletStep) factory.getObject(); assertEquals(25, bean.getStartLimit(), "wrong start-limit:"); - Object throttleLimit = ReflectionTestUtils.getField(factory, "throttleLimit"); - assertEquals(10, throttleLimit); } @Test diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java index 806a30e5cb..a8669c4c37 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,8 +42,6 @@ import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; @@ -112,48 +110,6 @@ void testNoDatabaseType() throws Exception { } - @Test - void testOracleLobHandler() throws Exception { - - factory.setDatabaseType("ORACLE"); - - incrementerFactory = mock(); - when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) - .thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) - .thenReturn(new StubIncrementer()); - factory.setIncrementerFactory(incrementerFactory); - - factory.afterPropertiesSet(); - LobHandler lobHandler = (LobHandler) ReflectionTestUtils.getField(factory, "lobHandler"); - assertTrue(lobHandler instanceof DefaultLobHandler); - - } - - @Test - void testCustomLobHandler() throws Exception { - - factory.setDatabaseType("ORACLE"); - - incrementerFactory = mock(); - when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) - .thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) - .thenReturn(new StubIncrementer()); - factory.setIncrementerFactory(incrementerFactory); - - LobHandler lobHandler = new DefaultLobHandler(); - factory.setLobHandler(lobHandler); - - factory.afterPropertiesSet(); - assertEquals(lobHandler, ReflectionTestUtils.getField(factory, "lobHandler")); - - } - @Test @SuppressWarnings("unchecked") void tesDefaultSerializer() throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java index b3e1114d6f..61804ee1d4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -252,11 +252,6 @@ void testReturnedTypeOfTaskExecutorIsAssignableToSimpleStepBuilder() throws Exce testReturnedTypeOfSetterIsAssignableToSimpleStepBuilder(builder -> builder.taskExecutor(null)); } - @Test - void testReturnedTypeOfThrottleLimitIsAssignableToSimpleStepBuilder() throws Exception { - testReturnedTypeOfSetterIsAssignableToSimpleStepBuilder(builder -> builder.throttleLimit(4)); - } - @Test void testReturnedTypeOfExceptionHandlerIsAssignableToSimpleStepBuilder() throws Exception { testReturnedTypeOfSetterIsAssignableToSimpleStepBuilder( diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java index d4f6137dbb..4455756793 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -151,7 +151,6 @@ void testSimpleConcurrentJob() throws Exception { SimpleStepFactoryBean factory = getStepFactory("foo", "bar"); factory.setTaskExecutor(new SimpleAsyncTaskExecutor()); - factory.setThrottleLimit(1); AbstractStep step = (AbstractStep) factory.getObject(); step.setName("step1"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java index 5a3efbf659..323c89cd0a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -109,7 +109,6 @@ void init() { job = new JobSupport("FOO"); TaskExecutorRepeatTemplate repeatTemplate = new TaskExecutorRepeatTemplate(); - repeatTemplate.setThrottleLimit(2); repeatTemplate.setTaskExecutor(new SimpleAsyncTaskExecutor()); step.setStepOperations(repeatTemplate); step.setTransactionManager(transactionManager); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java index 5062972d08..7002c5275e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,7 +90,6 @@ private void setUp() { step.setJobRepository(jobRepository); TaskExecutorRepeatTemplate template = new TaskExecutorRepeatTemplate(); - template.setThrottleLimit(throttleLimit); SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); taskExecutor.setConcurrencyLimit(concurrencyLimit); template.setTaskExecutor(taskExecutor); diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml index 0537f41739..dccc63e23e 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests-context.xml @@ -13,7 +13,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml index 95b739c01a..1835e82948 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/test-context.xml @@ -10,7 +10,7 @@ http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd"> + class="org.springframework.batch.core.configuration.support.JobRegistrySmartInitializingSingleton"> diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/trivial-context-autoregister.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/trivial-context-autoregister.xml index cce014e578..e01d220d0a 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/trivial-context-autoregister.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/support/trivial-context-autoregister.xml @@ -11,7 +11,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml index ecbf6bbf36..240e5baa21 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests-context.xml @@ -20,7 +20,7 @@ + class="org.springframework.batch.core.configuration.support.JobRegistrySmartInitializingSingleton"> diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml index e7993737bd..ae15fc673c 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml @@ -14,9 +14,8 @@ - - + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml index 48f6ddedd3..68b7a04fe3 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepParserTaskletAttributesTests-context.xml @@ -9,7 +9,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml index 8620593d3d..c122971d17 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests-context.xml @@ -38,7 +38,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml index 39f42d9ad3..5cb22aea10 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/launcher-with-locator.xml @@ -15,7 +15,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml index eac8d8e9fb..6045e96aed 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml @@ -9,7 +9,7 @@ - + diff --git a/spring-batch-core/src/test/resources/simple-job-launcher-context.xml b/spring-batch-core/src/test/resources/simple-job-launcher-context.xml index 4e9986d0f6..1dbd4308a4 100644 --- a/spring-batch-core/src/test/resources/simple-job-launcher-context.xml +++ b/spring-batch-core/src/test/resources/simple-job-launcher-context.xml @@ -11,7 +11,7 @@ - + diff --git a/spring-batch-docs/modules/ROOT/pages/appendix.adoc b/spring-batch-docs/modules/ROOT/pages/appendix.adoc index 28d4ca344e..cbbb93e552 100644 --- a/spring-batch-docs/modules/ROOT/pages/appendix.adoc +++ b/spring-batch-docs/modules/ROOT/pages/appendix.adoc @@ -52,11 +52,10 @@ This reader stores message offsets in the execution context to support restart c rows, such that large datasets can be read without running out of memory.|Yes |`ListItemReader`|Provides the items from a list, one at a time.|No -|`MongoItemReader`|Given a `MongoOperations` object and a JSON-based MongoDB +|`MongoPagingItemReader`|Given a `MongoOperations` object and a JSON-based MongoDB query, provides items received from the `MongoOperations#find()` method.|Yes -|`Neo4jItemReader`|Given a `Neo4jOperations` object and the components of a - Cyhper query, items are returned as the result of the Neo4jOperations.query - method.|Yes +|`MongoCursorItemReader`|Given a `MongoOperations` object and a JSON-based MongoDB + query, provides items received from the `MongoOperations#stream()` method.|Yes |`RepositoryItemReader`|Given a Spring Data `PagingAndSortingRepository` object, a `Sort`, and the name of method to execute, returns items provided by the Spring Data repository implementation.|Yes @@ -106,9 +105,6 @@ This reader stores message offsets in the execution context to support restart c |`MongoItemWriter`|Given a `MongoOperations` object, items are written through the `MongoOperations.save(Object)` method. The actual write is delayed until the last possible moment before the transaction commits.|Yes -|`Neo4jItemWriter`|Given a `Neo4jOperations` object, items are persisted through the - `save(Object)` method or deleted through the `delete(Object)`, as dictated by the - `ItemWriter's` configuration|Yes |`PropertyExtractingDelegatingItemWriter`|Extends `AbstractMethodInvokingDelegator` creating arguments on the fly. Arguments are created by retrieving the values from the fields in the item to be processed (through a diff --git a/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc b/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc index bfa7ff3d1a..4102a8460f 100644 --- a/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc +++ b/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc @@ -177,58 +177,6 @@ You can populate a `JobRegistry` in one of the following ways: by using a bean post processor, or by using a smart initializing singleton or by using a registrar lifecycle component. The coming sections describe these mechanisms. -[[jobregistrybeanpostprocessor]] -=== JobRegistryBeanPostProcessor - -This is a bean post-processor that can register all jobs as they are created. - -[tabs] -==== -Java:: -+ -The following example shows how to include the `JobRegistryBeanPostProcessor` for a job -defined in Java: -+ -.Java Configuration -[source, java] ----- -@Bean -public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) { - JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor(); - postProcessor.setJobRegistry(jobRegistry); - return postProcessor; -} ----- - -XML:: -+ -The following example shows how to include the `JobRegistryBeanPostProcessor` for a job -defined in XML: -+ -.XML Configuration -[source, xml] ----- - - - ----- - -==== - - - -Although it is not strictly necessary, the post-processor in the -example has been given an `id` so that it can be included in child -contexts (for example, as a parent bean definition) and cause all jobs created -there to also be registered automatically. - -[WARNING] -.Deprecation -==== -As of version 5.2, the `JobRegistryBeanPostProcessor` class is deprecated in favor of -`JobRegistrySmartInitializingSingleton`, see xref:#jobregistrysmartinitializingsingleton[JobRegistrySmartInitializingSingleton]. -==== - [[jobregistrysmartinitializingsingleton]] === JobRegistrySmartInitializingSingleton @@ -343,7 +291,7 @@ configuration in the child, provided it should be the same as the parent. You can use `AutomaticJobRegistrar` in -conjunction with a `JobRegistryBeanPostProcessor` +conjunction with a `JobRegistrySmartInitializingSingleton` (as long as you also use `DefaultJobLoader`). For instance, this might be desirable if there are jobs defined in the main parent context as well as in the child diff --git a/spring-batch-docs/modules/ROOT/pages/readers-and-writers/item-reader-writer-implementations.adoc b/spring-batch-docs/modules/ROOT/pages/readers-and-writers/item-reader-writer-implementations.adoc index 628b2b85b7..4f3e165925 100644 --- a/spring-batch-docs/modules/ROOT/pages/readers-and-writers/item-reader-writer-implementations.adoc +++ b/spring-batch-docs/modules/ROOT/pages/readers-and-writers/item-reader-writer-implementations.adoc @@ -161,21 +161,21 @@ construct an instance of the `KafkaItemWriter`. == Database Readers Spring Batch offers the following database readers: -* xref:readers-and-writers/item-reader-writer-implementations.adoc#Neo4jItemReader[`Neo4jItemReader`] -* xref:readers-and-writers/item-reader-writer-implementations.adoc#mongoItemReader[`MongoItemReader`] +* xref:readers-and-writers/item-reader-writer-implementations.adoc#mongoPagingItemReader[`MongoPagingItemReader`] +* xref:readers-and-writers/item-reader-writer-implementations.adoc#mongoCursorItemReader[`MongoCursorItemReader`] * xref:readers-and-writers/item-reader-writer-implementations.adoc#repositoryItemReader[`RepositoryItemReader`] -[[Neo4jItemReader]] -=== `Neo4jItemReader` -The `Neo4jItemReader` is an `ItemReader` that reads objects from the graph database Neo4j -by using a paging technique. Spring Batch provides a `Neo4jItemReaderBuilder` to -construct an instance of the `Neo4jItemReader`. +[[mongoPagingItemReader]] +=== `MongoPagingItemReader` +The `MongoPagingItemReader` is an `ItemReader` that reads documents from MongoDB by using a +paging technique. Spring Batch provides a `MongoPagingItemReaderBuilder` to construct an +instance of the `MongoPagingItemReader`. -[[mongoItemReader]] -=== `MongoItemReader` -The `MongoItemReader` is an `ItemReader` that reads documents from MongoDB by using a -paging technique. Spring Batch provides a `MongoItemReaderBuilder` to construct an -instance of the `MongoItemReader`. +[[mongoCursorItemReader]] +=== `MongoCursorItemReader` +The `MongoCursorItemReader` is an `ItemReader` that reads documents from MongoDB by using a +streaming technique. Spring Batch provides a `MongoCursorItemReaderBuilder` to construct an +instance of the `MongoCursorItemReader`. [[repositoryItemReader]] === `RepositoryItemReader` @@ -187,18 +187,11 @@ construct an instance of the `RepositoryItemReader`. == Database Writers Spring Batch offers the following database writers: -* xref:readers-and-writers/item-reader-writer-implementations.adoc#neo4jItemWriter[`Neo4jItemWriter`] * xref:readers-and-writers/item-reader-writer-implementations.adoc#mongoItemWriter[`MongoItemWriter`] * xref:readers-and-writers/item-reader-writer-implementations.adoc#repositoryItemWriter[`RepositoryItemWriter`] * xref:readers-and-writers/item-reader-writer-implementations.adoc#jdbcBatchItemWriter[`JdbcBatchItemWriter`] * xref:readers-and-writers/item-reader-writer-implementations.adoc#jpaItemWriter[`JpaItemWriter`] -[[neo4jItemWriter]] -=== `Neo4jItemWriter` -The `Neo4jItemWriter` is an `ItemWriter` implementation that writes to a Neo4j database. -Spring Batch provides a `Neo4jItemWriterBuilder` to construct an instance of the -`Neo4jItemWriter`. - [[mongoItemWriter]] === `MongoItemWriter` The `MongoItemWriter` is an `ItemWriter` implementation that writes to a MongoDB store diff --git a/spring-batch-docs/modules/ROOT/pages/scalability.adoc b/spring-batch-docs/modules/ROOT/pages/scalability.adoc index b00353c4e6..48f711e6b2 100644 --- a/spring-batch-docs/modules/ROOT/pages/scalability.adoc +++ b/spring-batch-docs/modules/ROOT/pages/scalability.adoc @@ -133,29 +133,6 @@ Note also that there may be limits placed on concurrency by any pooled resources your step, such as a `DataSource`. Be sure to make the pool in those resources at least as large as the desired number of concurrent threads in the step. -[WARNING] -.Throttle limit deprecation -==== -As of v5.0, the throttle limit is deprecated with no replacement. If you want to replace the -current throttling mechanism in the default `TaskExecutorRepeatTemplate`, you need to provide -a custom `RepeatOperations` implementation (based on a `TaskExecutor` with a bounded task queue) -and set it on the step with `StepBuilder#stepOperations`: - -.Java Configuration -[source, java] ----- -@Bean -public Step sampleStep(RepeatOperations customRepeatOperations, JobRepository jobRepository, PlatformTransactionManager transactionManager) { - return new StepBuilder("sampleStep", jobRepository) - .chunk(10, transactionManager) - .reader(itemReader()) - .writer(itemWriter()) - .stepOperations(customRepeatOperations) - .build(); -} ----- -==== - There are some practical limitations of using multi-threaded `Step` implementations for some common batch use cases. Many participants in a `Step` (such as readers and writers) are stateful. If the state is not segregated by thread, those components are not diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java deleted file mode 100644 index 9c8ce109d6..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.bson.Document; -import org.bson.codecs.DecoderContext; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.query.BasicQuery; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; -import org.springframework.data.mongodb.util.json.ParameterBindingJsonReader; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -/** - *

    - * Restartable {@link ItemReader} that reads documents from MongoDB via a paging - * technique. - *

    - * - *

    - * If you set JSON String query {@link #setQuery(String)} then it executes the JSON to - * retrieve the requested documents. - *

    - * - *

    - * If you set Query object {@link #setQuery(Query)} then it executes the Query to retrieve - * the requested documents. - *

    - * - *

    - * The query is executed using paged requests specified in the {@link #setPageSize(int)}. - * Additional pages are requested as needed to provide data when the {@link #read()} - * method is called. - *

    - * - *

    - * The JSON String query provided supports parameter substitution via ?<index> - * placeholders where the <index> indicates the index of the parameterValue to - * substitute. - *

    - * - *

    - * The implementation is thread-safe between calls to {@link #open(ExecutionContext)}, but - * remember to use saveState=false if used in a multi-threaded client (no - * restart available). - *

    - * - * @author Michael Minella - * @author Takaaki Iida - * @author Mahmoud Ben Hassine - * @author Parikshit Dutta - * @deprecated Use {@link MongoPagingItemReader} instead. Scheduled for removal in v5.3 or - * later. - */ -@Deprecated(since = "5.1", forRemoval = true) -public class MongoItemReader extends AbstractPaginatedDataItemReader implements InitializingBean { - - protected MongoOperations template; - - protected Query query; - - protected String queryString; - - protected Class type; - - protected Sort sort; - - protected String hint; - - protected String fields; - - protected String collection; - - protected List parameterValues = new ArrayList<>(); - - public MongoItemReader() { - super(); - setName(ClassUtils.getShortName(MongoItemReader.class)); - } - - /** - * A Mongo Query to be used. - * @param query Mongo Query to be used. - */ - public void setQuery(Query query) { - this.query = query; - } - - /** - * Used to perform operations against the MongoDB instance. Also handles the mapping - * of documents to objects. - * @param template the MongoOperations instance to use - * @see MongoOperations - */ - public void setTemplate(MongoOperations template) { - this.template = template; - } - - /** - * A JSON formatted MongoDB query. Parameterization of the provided query is allowed - * via ?<index> placeholders where the <index> indicates the index of the - * parameterValue to substitute. - * @param queryString JSON formatted Mongo query - */ - public void setQuery(String queryString) { - this.queryString = queryString; - } - - /** - * The type of object to be returned for each {@link #read()} call. - * @param type the type of object to return - */ - public void setTargetType(Class type) { - this.type = type; - } - - /** - * {@link List} of values to be substituted in for each of the parameters in the - * query. - * @param parameterValues values - */ - public void setParameterValues(List parameterValues) { - Assert.notNull(parameterValues, "Parameter values must not be null"); - this.parameterValues = parameterValues; - } - - /** - * JSON defining the fields to be returned from the matching documents by MongoDB. - * @param fields JSON string that identifies the fields to sort by. - */ - public void setFields(String fields) { - this.fields = fields; - } - - /** - * {@link Map} of property - * names/{@link org.springframework.data.domain.Sort.Direction} values to sort the - * input by. - * @param sorts map of properties and direction to sort each. - */ - public void setSort(Map sorts) { - Assert.notNull(sorts, "Sorts must not be null"); - this.sort = convertToSort(sorts); - } - - /** - * @param collection Mongo collection to be queried. - */ - public void setCollection(String collection) { - this.collection = collection; - } - - /** - * JSON String telling MongoDB what index to use. - * @param hint string indicating what index to use. - */ - public void setHint(String hint) { - this.hint = hint; - } - - @Override - @SuppressWarnings("unchecked") - protected Iterator doPageRead() { - if (queryString != null) { - Pageable pageRequest = PageRequest.of(page, pageSize, sort); - - String populatedQuery = replacePlaceholders(queryString, parameterValues); - - Query mongoQuery; - - if (StringUtils.hasText(fields)) { - mongoQuery = new BasicQuery(populatedQuery, fields); - } - else { - mongoQuery = new BasicQuery(populatedQuery); - } - - mongoQuery.with(pageRequest); - - if (StringUtils.hasText(hint)) { - mongoQuery.withHint(hint); - } - - if (StringUtils.hasText(collection)) { - return (Iterator) template.find(mongoQuery, type, collection).iterator(); - } - else { - return (Iterator) template.find(mongoQuery, type).iterator(); - } - - } - else { - Pageable pageRequest = PageRequest.of(page, pageSize); - query.with(pageRequest); - - if (StringUtils.hasText(collection)) { - return (Iterator) template.find(query, type, collection).iterator(); - } - else { - return (Iterator) template.find(query, type).iterator(); - } - } - } - - /** - * Checks mandatory properties - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(template != null, "An implementation of MongoOperations is required."); - Assert.state(type != null, "A type to convert the input into is required."); - Assert.state(queryString != null || query != null, "A query is required."); - - if (queryString != null) { - Assert.state(sort != null, "A sort is required."); - } - } - - protected String replacePlaceholders(String input, List values) { - ParameterBindingJsonReader reader = new ParameterBindingJsonReader(input, values.toArray()); - DecoderContext decoderContext = DecoderContext.builder().build(); - Document document = new ParameterBindingDocumentCodec().decode(reader, decoderContext); - return document.toJson(); - } - - protected Sort convertToSort(Map sorts) { - List sortValues = new ArrayList<>(sorts.size()); - - for (Map.Entry curSort : sorts.entrySet()) { - sortValues.add(new Sort.Order(curSort.getValue(), curSort.getKey())); - } - - return Sort.by(sortValues); - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java index b7aa27f375..6e8219512d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -97,19 +97,6 @@ public MongoItemWriter() { this.bufferKey = new Object(); } - /** - * Indicates if the items being passed to the writer are to be saved or removed from - * the data store. If set to false (default), the items will be saved or update using - * {@link Mode#UPSERT}. If set to true, then items will be removed. - * @param delete removal indicator - * @deprecated use {@link MongoItemWriter#setMode(Mode)} instead. Scheduled for - * removal in v5.3 or later. - */ - @Deprecated(since = "5.1", forRemoval = true) - public void setDelete(boolean delete) { - this.mode = (delete) ? Mode.REMOVE : Mode.UPSERT; - } - /** * Set the operating {@link Mode} to be applied by this writer. Defaults to * {@link Mode#UPSERT}. diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoPagingItemReader.java index 5c2278cacc..e9e8ff83d0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoPagingItemReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,16 +15,27 @@ */ package org.springframework.batch.item.data; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; +import org.bson.Document; +import org.bson.codecs.DecoderContext; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemReader; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec; +import org.springframework.data.mongodb.util.json.ParameterBindingJsonReader; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; /** *

    @@ -67,78 +78,186 @@ * @author Mahmoud Ben Hassine * @author Parikshit Dutta */ -public class MongoPagingItemReader extends MongoItemReader { +public class MongoPagingItemReader extends AbstractPaginatedDataItemReader implements InitializingBean { + + protected MongoOperations template; + + protected Query query; + + protected String queryString; + + protected Class type; + + protected Sort sort; + + protected String hint; + + protected String fields; + + protected String collection; + + protected List parameterValues = new ArrayList<>(); - /** - * Create a new {@link MongoPagingItemReader}. - */ public MongoPagingItemReader() { + super(); setName(ClassUtils.getShortName(MongoPagingItemReader.class)); } - @Override - public void setTemplate(MongoOperations template) { - super.setTemplate(template); + /** + * A Mongo Query to be used. + * @param query Mongo Query to be used. + */ + public void setQuery(Query query) { + this.query = query; } - @Override - public void setQuery(Query query) { - super.setQuery(query); + /** + * Used to perform operations against the MongoDB instance. Also handles the mapping + * of documents to objects. + * @param template the MongoOperations instance to use + * @see MongoOperations + */ + public void setTemplate(MongoOperations template) { + this.template = template; } - @Override + /** + * A JSON formatted MongoDB query. Parameterization of the provided query is allowed + * via ?<index> placeholders where the <index> indicates the index of the + * parameterValue to substitute. + * @param queryString JSON formatted Mongo query + */ public void setQuery(String queryString) { - super.setQuery(queryString); + this.queryString = queryString; } - @Override + /** + * The type of object to be returned for each {@link #read()} call. + * @param type the type of object to return + */ public void setTargetType(Class type) { - super.setTargetType(type); + this.type = type; } - @Override + /** + * {@link List} of values to be substituted in for each of the parameters in the + * query. + * @param parameterValues values + */ public void setParameterValues(List parameterValues) { - super.setParameterValues(parameterValues); + Assert.notNull(parameterValues, "Parameter values must not be null"); + this.parameterValues = parameterValues; } - @Override + /** + * JSON defining the fields to be returned from the matching documents by MongoDB. + * @param fields JSON string that identifies the fields to sort by. + */ public void setFields(String fields) { - super.setFields(fields); + this.fields = fields; } - @Override + /** + * {@link Map} of property + * names/{@link org.springframework.data.domain.Sort.Direction} values to sort the + * input by. + * @param sorts map of properties and direction to sort each. + */ public void setSort(Map sorts) { - super.setSort(sorts); + Assert.notNull(sorts, "Sorts must not be null"); + this.sort = convertToSort(sorts); } - @Override + /** + * @param collection Mongo collection to be queried. + */ public void setCollection(String collection) { - super.setCollection(collection); + this.collection = collection; } - @Override + /** + * JSON String telling MongoDB what index to use. + * @param hint string indicating what index to use. + */ public void setHint(String hint) { - super.setHint(hint); + this.hint = hint; } @Override - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); + @SuppressWarnings("unchecked") + protected Iterator doPageRead() { + if (queryString != null) { + Pageable pageRequest = PageRequest.of(page, pageSize, sort); + + String populatedQuery = replacePlaceholders(queryString, parameterValues); + + Query mongoQuery; + + if (StringUtils.hasText(fields)) { + mongoQuery = new BasicQuery(populatedQuery, fields); + } + else { + mongoQuery = new BasicQuery(populatedQuery); + } + + mongoQuery.with(pageRequest); + + if (StringUtils.hasText(hint)) { + mongoQuery.withHint(hint); + } + + if (StringUtils.hasText(collection)) { + return (Iterator) template.find(mongoQuery, type, collection).iterator(); + } + else { + return (Iterator) template.find(mongoQuery, type).iterator(); + } + + } + else { + Pageable pageRequest = PageRequest.of(page, pageSize); + query.with(pageRequest); + + if (StringUtils.hasText(collection)) { + return (Iterator) template.find(query, type, collection).iterator(); + } + else { + return (Iterator) template.find(query, type).iterator(); + } + } } + /** + * Checks mandatory properties + * + * @see InitializingBean#afterPropertiesSet() + */ @Override - protected Iterator doPageRead() { - return super.doPageRead(); + public void afterPropertiesSet() throws Exception { + Assert.state(template != null, "An implementation of MongoOperations is required."); + Assert.state(type != null, "A type to convert the input into is required."); + Assert.state(queryString != null || query != null, "A query is required."); + + if (queryString != null) { + Assert.state(sort != null, "A sort is required."); + } } - @Override protected String replacePlaceholders(String input, List values) { - return super.replacePlaceholders(input, values); + ParameterBindingJsonReader reader = new ParameterBindingJsonReader(input, values.toArray()); + DecoderContext decoderContext = DecoderContext.builder().build(); + Document document = new ParameterBindingDocumentCodec().decode(reader, decoderContext); + return document.toJson(); } - @Override protected Sort convertToSort(Map sorts) { - return super.convertToSort(sorts); + List sortValues = new ArrayList<>(sorts.size()); + + for (Map.Entry curSort : sorts.entrySet()) { + sortValues.add(new Sort.Order(curSort.getValue(), curSort.getKey())); + } + + return Sort.by(sortValues); } -} +} \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java deleted file mode 100644 index 07daeaa9d6..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2012-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.ItemReader; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - *

    - * Restartable {@link ItemReader} that reads objects from the graph database Neo4j via a - * paging technique. - *

    - * - *

    - * It executes cypher queries built from the statement fragments provided to retrieve the - * requested data. The query is executed using paged requests of a size specified in - * {@link #setPageSize(int)}. Additional pages are requested as needed when the - * {@link #read()} method is called. On restart, the reader will begin again at the same - * number item it left off at. - *

    - * - *

    - * Performance is dependent on your Neo4J configuration (embedded or remote) as well as - * page size. Setting a fairly large page size and using a commit interval that matches - * the page size should provide better performance. - *

    - * - *

    - * This implementation is thread-safe between calls to - * {@link #open(org.springframework.batch.item.ExecutionContext)}, however you should set - * saveState=false if used in a multi-threaded environment (no restart - * available). - *

    - * - * @author Michael Minella - * @author Mahmoud Ben Hassine - * @deprecated since 5.0 in favor of the item reader from ... - */ -@Deprecated -public class Neo4jItemReader extends AbstractPaginatedDataItemReader implements InitializingBean { - - protected Log logger = LogFactory.getLog(getClass()); - - private SessionFactory sessionFactory; - - private String startStatement; - - private String returnStatement; - - private String matchStatement; - - private String whereStatement; - - private String orderByStatement; - - private Class targetType; - - private Map parameterValues; - - /** - * Optional parameters to be used in the cypher query. - * @param parameterValues the parameter values to be used in the cypher query - */ - public void setParameterValues(Map parameterValues) { - this.parameterValues = parameterValues; - } - - protected final Map getParameterValues() { - return this.parameterValues; - } - - /** - * The start segment of the cypher query. START is prepended to the statement provided - * and should not be included. - * @param startStatement the start fragment of the cypher query. - */ - public void setStartStatement(String startStatement) { - this.startStatement = startStatement; - } - - /** - * The return statement of the cypher query. RETURN is prepended to the statement - * provided and should not be included - * @param returnStatement the return fragment of the cypher query. - */ - public void setReturnStatement(String returnStatement) { - this.returnStatement = returnStatement; - } - - /** - * An optional match fragment of the cypher query. MATCH is prepended to the statement - * provided and should not be included. - * @param matchStatement the match fragment of the cypher query - */ - public void setMatchStatement(String matchStatement) { - this.matchStatement = matchStatement; - } - - /** - * An optional where fragment of the cypher query. WHERE is prepended to the statement - * provided and should not be included. - * @param whereStatement where fragment of the cypher query - */ - public void setWhereStatement(String whereStatement) { - this.whereStatement = whereStatement; - } - - /** - * A list of properties to order the results by. This is required so that subsequent - * page requests pull back the segment of results correctly. ORDER BY is prepended to - * the statement provided and should not be included. - * @param orderByStatement order by fragment of the cypher query. - */ - public void setOrderByStatement(String orderByStatement) { - this.orderByStatement = orderByStatement; - } - - protected SessionFactory getSessionFactory() { - return sessionFactory; - } - - /** - * Establish the session factory for the reader. - * @param sessionFactory the factory to use for the reader. - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - /** - * The object type to be returned from each call to {@link #read()} - * @param targetType the type of object to return. - */ - public void setTargetType(Class targetType) { - this.targetType = targetType; - } - - protected final Class getTargetType() { - return this.targetType; - } - - protected String generateLimitCypherQuery() { - StringBuilder query = new StringBuilder(128); - - query.append("START ").append(startStatement); - query.append(matchStatement != null ? " MATCH " + matchStatement : ""); - query.append(whereStatement != null ? " WHERE " + whereStatement : ""); - query.append(" RETURN ").append(returnStatement); - query.append(" ORDER BY ").append(orderByStatement); - query.append(" SKIP ").append(pageSize * page); - query.append(" LIMIT ").append(pageSize); - - String resultingQuery = query.toString(); - - if (logger.isDebugEnabled()) { - logger.debug(resultingQuery); - } - - return resultingQuery; - } - - /** - * Checks mandatory properties - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(sessionFactory != null, "A SessionFactory is required"); - Assert.state(targetType != null, "The type to be returned is required"); - Assert.state(StringUtils.hasText(startStatement), "A START statement is required"); - Assert.state(StringUtils.hasText(returnStatement), "A RETURN statement is required"); - Assert.state(StringUtils.hasText(orderByStatement), "A ORDER BY statement is required"); - } - - @SuppressWarnings("unchecked") - @Override - protected Iterator doPageRead() { - Session session = getSessionFactory().openSession(); - - Iterable queryResults = session.query(getTargetType(), generateLimitCypherQuery(), getParameterValues()); - - if (queryResults != null) { - return queryResults.iterator(); - } - else { - return new ArrayList().iterator(); - } - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java deleted file mode 100644 index c9bcd35bf6..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ItemWriter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - *

    - * A {@link ItemWriter} implementation that writes to a Neo4j database. - *

    - * - *

    - * This writer is thread-safe once all properties are set (normal singleton behavior) so - * it can be used in multiple concurrent transactions. - *

    - * - * @author Michael Minella - * @author Glenn Renfro - * @author Mahmoud Ben Hassine - * @deprecated since 5.0 in favor of the item writer from ... - * - */ -@Deprecated -public class Neo4jItemWriter implements ItemWriter, InitializingBean { - - protected static final Log logger = LogFactory.getLog(Neo4jItemWriter.class); - - private boolean delete = false; - - private SessionFactory sessionFactory; - - /** - * Boolean flag indicating whether the writer should save or delete the item at write - * time. - * @param delete true if write should delete item, false if item should be saved. - * Default is false. - */ - public void setDelete(boolean delete) { - this.delete = delete; - } - - /** - * Establish the session factory that will be used to create {@link Session} instances - * for interacting with Neo4j. - * @param sessionFactory sessionFactory to be used. - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - /** - * Checks mandatory properties - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(this.sessionFactory != null, "A SessionFactory is required"); - } - - /** - * Write all items to the data store. - * - * @see org.springframework.batch.item.ItemWriter#write(Chunk) - */ - @Override - public void write(Chunk chunk) throws Exception { - if (!chunk.isEmpty()) { - doWrite(chunk); - } - } - - /** - * Performs the actual write using the template. This can be overridden by a subclass - * if necessary. - * @param items the list of items to be persisted. - */ - protected void doWrite(Chunk items) { - if (delete) { - delete(items); - } - else { - save(items); - } - } - - private void delete(Chunk items) { - Session session = this.sessionFactory.openSession(); - - for (T item : items) { - session.delete(item); - } - } - - private void save(Chunk items) { - Session session = this.sessionFactory.openSession(); - - for (T item : items) { - session.save(item); - } - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java deleted file mode 100644 index 17747b8212..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2017-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data.builder; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.springframework.batch.item.data.MongoItemReader; -import org.springframework.data.domain.Sort; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * A builder implementation for the {@link MongoItemReader} - * - * @author Glenn Renfro - * @author Mahmoud Ben Hassine - * @author Drummond Dawson - * @author Parikshit Dutta - * @since 4.0 - * @see MongoItemReader - * @deprecated Use {@link MongoPagingItemReaderBuilder} instead. Scheduled for removal in - * v5.3 or later. - */ -@Deprecated(since = "5.1", forRemoval = true) -public class MongoItemReaderBuilder { - - protected MongoOperations template; - - protected String jsonQuery; - - protected Class targetType; - - protected Map sorts; - - protected String hint; - - protected String fields; - - protected String collection; - - protected List parameterValues = new ArrayList<>(); - - protected int pageSize = 10; - - protected boolean saveState = true; - - protected String name; - - protected int maxItemCount = Integer.MAX_VALUE; - - protected int currentItemCount; - - protected Query query; - - /** - * Configure if the state of the - * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within - * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. - * @param saveState defaults to true - * @return The current instance of the builder. - */ - public MongoItemReaderBuilder saveState(boolean saveState) { - this.saveState = saveState; - - return this; - } - - /** - * The name used to calculate the key within the - * {@link org.springframework.batch.item.ExecutionContext}. Required if - * {@link #saveState(boolean)} is set to true. - * @param name name of the reader instance - * @return The current instance of the builder. - * @see org.springframework.batch.item.ItemStreamSupport#setName(String) - */ - public MongoItemReaderBuilder name(String name) { - this.name = name; - - return this; - } - - /** - * Configure the max number of items to be read. - * @param maxItemCount the max items to be read - * @return The current instance of the builder. - * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) - */ - public MongoItemReaderBuilder maxItemCount(int maxItemCount) { - this.maxItemCount = maxItemCount; - - return this; - } - - /** - * Index for the current item. Used on restarts to indicate where to start from. - * @param currentItemCount current index - * @return this instance for method chaining - * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) - */ - public MongoItemReaderBuilder currentItemCount(int currentItemCount) { - this.currentItemCount = currentItemCount; - - return this; - } - - /** - * Used to perform operations against the MongoDB instance. Also handles the mapping - * of documents to objects. - * @param template the MongoOperations instance to use - * @see MongoOperations - * @return The current instance of the builder - * @see MongoItemReader#setTemplate(MongoOperations) - */ - public MongoItemReaderBuilder template(MongoOperations template) { - this.template = template; - - return this; - } - - /** - * A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is - * allowed via ?<index> placeholders where the <index> indicates the index - * of the parameterValue to substitute. - * @param query JSON formatted Mongo jsonQuery - * @return The current instance of the builder - * @see MongoItemReader#setQuery(String) - */ - public MongoItemReaderBuilder jsonQuery(String query) { - this.jsonQuery = query; - - return this; - } - - /** - * The type of object to be returned for each {@link MongoItemReader#read()} call. - * @param targetType the type of object to return - * @return The current instance of the builder - * @see MongoItemReader#setTargetType(Class) - */ - public MongoItemReaderBuilder targetType(Class targetType) { - this.targetType = targetType; - - return this; - } - - /** - * {@link List} of values to be substituted in for each of the parameters in the - * query. - * @param parameterValues values - * @return The current instance of the builder - * @see MongoItemReader#setParameterValues(List) - */ - public MongoItemReaderBuilder parameterValues(List parameterValues) { - this.parameterValues = parameterValues; - - return this; - } - - /** - * Values to be substituted in for each of the parameters in the query. - * @param parameterValues values - * @return The current instance of the builder - * @see MongoItemReader#setParameterValues(List) - */ - public MongoItemReaderBuilder parameterValues(Object... parameterValues) { - return parameterValues(Arrays.asList(parameterValues)); - } - - /** - * JSON defining the fields to be returned from the matching documents by MongoDB. - * @param fields JSON string that identifies the fields to sort by. - * @return The current instance of the builder - * @see MongoItemReader#setFields(String) - */ - public MongoItemReaderBuilder fields(String fields) { - this.fields = fields; - - return this; - } - - /** - * {@link Map} of property - * names/{@link org.springframework.data.domain.Sort.Direction} values to sort the - * input by. - * @param sorts map of properties and direction to sort each. - * @return The current instance of the builder - * @see MongoItemReader#setSort(Map) - */ - public MongoItemReaderBuilder sorts(Map sorts) { - this.sorts = sorts; - - return this; - } - - /** - * Establish an optional collection that can be queried. - * @param collection Mongo collection to be queried. - * @return The current instance of the builder - * @see MongoItemReader#setCollection(String) - */ - public MongoItemReaderBuilder collection(String collection) { - this.collection = collection; - - return this; - } - - /** - * JSON String telling MongoDB what index to use. - * @param hint string indicating what index to use. - * @return The current instance of the builder - * @see MongoItemReader#setHint(String) - */ - public MongoItemReaderBuilder hint(String hint) { - this.hint = hint; - - return this; - } - - /** - * The number of items to be read with each page. - * @param pageSize the number of items - * @return this instance for method chaining - * @see MongoItemReader#setPageSize(int) - */ - public MongoItemReaderBuilder pageSize(int pageSize) { - this.pageSize = pageSize; - - return this; - } - - /** - * Provide a Spring Data Mongo {@link Query}. This will take precedence over a JSON - * configured query. - * @param query Query to execute - * @return this instance for method chaining - * @see MongoItemReader#setQuery(Query) - */ - public MongoItemReaderBuilder query(Query query) { - this.query = query; - - return this; - } - - /** - * Validates and builds a {@link MongoItemReader}. - * @return a {@link MongoItemReader} - */ - public MongoItemReader build() { - Assert.notNull(this.template, "template is required."); - if (this.saveState) { - Assert.hasText(this.name, "A name is required when saveState is set to true"); - } - Assert.notNull(this.targetType, "targetType is required."); - Assert.state(StringUtils.hasText(this.jsonQuery) || this.query != null, "A query is required"); - - if (StringUtils.hasText(this.jsonQuery) || this.query != null) { - Assert.notNull(this.sorts, "sorts map is required."); - } - - MongoItemReader reader = new MongoItemReader<>(); - reader.setTemplate(this.template); - reader.setTargetType(this.targetType); - reader.setQuery(this.jsonQuery); - reader.setSort(this.sorts); - reader.setHint(this.hint); - reader.setFields(this.fields); - reader.setCollection(this.collection); - reader.setParameterValues(this.parameterValues); - reader.setQuery(this.query); - - reader.setPageSize(this.pageSize); - reader.setName(this.name); - reader.setSaveState(this.saveState); - reader.setCurrentItemCount(this.currentItemCount); - reader.setMaxItemCount(this.maxItemCount); - - return reader; - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java index 4df60a7d4c..e2cfdcdb48 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 the original author or authors. + * Copyright 2017-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,23 +37,6 @@ public class MongoItemWriterBuilder { private Mode mode = Mode.UPSERT; - /** - * Indicates if the items being passed to the writer are to be saved or removed from - * the data store. If set to false (default), the items will be saved. If set to true, - * the items will be removed. - * @param delete removal indicator - * @return The current instance of the builder - * @see MongoItemWriter#setDelete(boolean) - * @deprecated Use {@link MongoItemWriterBuilder#mode(Mode)} instead. Scheduled for - * removal in v5.3 or later. - */ - @Deprecated(since = "5.1", forRemoval = true) - public MongoItemWriterBuilder delete(boolean delete) { - this.mode = (delete) ? Mode.REMOVE : Mode.UPSERT; - - return this; - } - /** * Set the operating {@link Mode} to be applied by this writer. Defaults to * {@link Mode#UPSERT}. diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoPagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoPagingItemReaderBuilder.java index 286f043f0e..480b3a7c92 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoPagingItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoPagingItemReaderBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2023 the original author or authors. + * Copyright 2017-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package org.springframework.batch.item.data.builder; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -36,7 +37,35 @@ * @author Parikshit Dutta * @since 5.1 */ -public class MongoPagingItemReaderBuilder extends MongoItemReaderBuilder { +public class MongoPagingItemReaderBuilder { + + protected MongoOperations template; + + protected String jsonQuery; + + protected Class targetType; + + protected Map sorts; + + protected String hint; + + protected String fields; + + protected String collection; + + protected List parameterValues = new ArrayList<>(); + + protected int pageSize = 10; + + protected boolean saveState = true; + + protected String name; + + protected int maxItemCount = Integer.MAX_VALUE; + + protected int currentItemCount; + + protected Query query; /** * Configure if the state of the @@ -228,7 +257,6 @@ public MongoPagingItemReaderBuilder query(Query query) { return this; } - @Override public MongoPagingItemReader build() { Assert.notNull(this.template, "template is required."); if (this.saveState) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java deleted file mode 100644 index 1884d2b181..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2017-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data.builder; - -import java.util.Map; - -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.data.Neo4jItemReader; -import org.springframework.util.Assert; - -/** - * A builder for the {@link Neo4jItemReader}. - * - * @author Glenn Renfro - * @author Mahmoud Ben Hassine - * @since 4.0 - * @see Neo4jItemReader - * @deprecated since 5.0 in favor of the item reader builder from ... - */ -@Deprecated -public class Neo4jItemReaderBuilder { - - private SessionFactory sessionFactory; - - private String startStatement; - - private String returnStatement; - - private String matchStatement; - - private String whereStatement; - - private String orderByStatement; - - private Class targetType; - - private Map parameterValues; - - private int pageSize = 10; - - private boolean saveState = true; - - private String name; - - private int maxItemCount = Integer.MAX_VALUE; - - private int currentItemCount; - - /** - * Configure if the state of the - * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within - * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. - * @param saveState defaults to true - * @return The current instance of the builder. - */ - public Neo4jItemReaderBuilder saveState(boolean saveState) { - this.saveState = saveState; - - return this; - } - - /** - * The name used to calculate the key within the - * {@link org.springframework.batch.item.ExecutionContext}. Required if - * {@link #saveState(boolean)} is set to true. - * @param name name of the reader instance - * @return The current instance of the builder. - * @see org.springframework.batch.item.ItemStreamSupport#setName(String) - */ - public Neo4jItemReaderBuilder name(String name) { - this.name = name; - - return this; - } - - /** - * Configure the max number of items to be read. - * @param maxItemCount the max items to be read - * @return The current instance of the builder. - * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) - */ - public Neo4jItemReaderBuilder maxItemCount(int maxItemCount) { - this.maxItemCount = maxItemCount; - - return this; - } - - /** - * Index for the current item. Used on restarts to indicate where to start from. - * @param currentItemCount current index - * @return this instance for method chaining - * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) - */ - public Neo4jItemReaderBuilder currentItemCount(int currentItemCount) { - this.currentItemCount = currentItemCount; - - return this; - } - - /** - * Establish the session factory for the reader. - * @param sessionFactory the factory to use for the reader. - * @return this instance for method chaining - * @see Neo4jItemReader#setSessionFactory(SessionFactory) - */ - public Neo4jItemReaderBuilder sessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - - return this; - } - - /** - * The number of items to be read with each page. - * @param pageSize the number of items - * @return this instance for method chaining - * @see Neo4jItemReader#setPageSize(int) - */ - public Neo4jItemReaderBuilder pageSize(int pageSize) { - this.pageSize = pageSize; - - return this; - } - - /** - * Optional parameters to be used in the cypher query. - * @param parameterValues the parameter values to be used in the cypher query - * @return this instance for method chaining - * @see Neo4jItemReader#setParameterValues(Map) - */ - public Neo4jItemReaderBuilder parameterValues(Map parameterValues) { - this.parameterValues = parameterValues; - - return this; - } - - /** - * The start segment of the cypher query. START is prepended to the statement provided - * and should not be included. - * @param startStatement the start fragment of the cypher query. - * @return this instance for method chaining - * @see Neo4jItemReader#setStartStatement(String) - */ - public Neo4jItemReaderBuilder startStatement(String startStatement) { - this.startStatement = startStatement; - - return this; - } - - /** - * The return statement of the cypher query. RETURN is prepended to the statement - * provided and should not be included - * @param returnStatement the return fragment of the cypher query. - * @return this instance for method chaining - * @see Neo4jItemReader#setReturnStatement(String) - */ - public Neo4jItemReaderBuilder returnStatement(String returnStatement) { - this.returnStatement = returnStatement; - - return this; - } - - /** - * An optional match fragment of the cypher query. MATCH is prepended to the statement - * provided and should not be included. - * @param matchStatement the match fragment of the cypher query - * @return this instance for method chaining - * @see Neo4jItemReader#setMatchStatement(String) - */ - public Neo4jItemReaderBuilder matchStatement(String matchStatement) { - this.matchStatement = matchStatement; - - return this; - } - - /** - * An optional where fragment of the cypher query. WHERE is prepended to the statement - * provided and should not be included. - * @param whereStatement where fragment of the cypher query - * @return this instance for method chaining - * @see Neo4jItemReader#setWhereStatement(String) - */ - public Neo4jItemReaderBuilder whereStatement(String whereStatement) { - this.whereStatement = whereStatement; - - return this; - } - - /** - * A list of properties to order the results by. This is required so that subsequent - * page requests pull back the segment of results correctly. ORDER BY is prepended to - * the statement provided and should not be included. - * @param orderByStatement order by fragment of the cypher query. - * @return this instance for method chaining - * @see Neo4jItemReader#setOrderByStatement(String) - */ - public Neo4jItemReaderBuilder orderByStatement(String orderByStatement) { - this.orderByStatement = orderByStatement; - - return this; - } - - /** - * The object type to be returned from each call to {@link Neo4jItemReader#read()} - * @param targetType the type of object to return. - * @return this instance for method chaining - * @see Neo4jItemReader#setTargetType(Class) - */ - public Neo4jItemReaderBuilder targetType(Class targetType) { - this.targetType = targetType; - - return this; - } - - /** - * Returns a fully constructed {@link Neo4jItemReader}. - * @return a new {@link Neo4jItemReader} - */ - public Neo4jItemReader build() { - if (this.saveState) { - Assert.hasText(this.name, "A name is required when saveState is set to true"); - } - Assert.notNull(this.sessionFactory, "sessionFactory is required."); - Assert.notNull(this.targetType, "targetType is required."); - Assert.hasText(this.startStatement, "startStatement is required."); - Assert.hasText(this.returnStatement, "returnStatement is required."); - Assert.hasText(this.orderByStatement, "orderByStatement is required."); - Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero"); - Assert.isTrue(this.maxItemCount > 0, "maxItemCount must be greater than zero"); - Assert.isTrue(this.maxItemCount > this.currentItemCount, "maxItemCount must be greater than currentItemCount"); - - Neo4jItemReader reader = new Neo4jItemReader<>(); - reader.setMatchStatement(this.matchStatement); - reader.setOrderByStatement(this.orderByStatement); - reader.setPageSize(this.pageSize); - reader.setParameterValues(this.parameterValues); - reader.setSessionFactory(this.sessionFactory); - reader.setTargetType(this.targetType); - reader.setStartStatement(this.startStatement); - reader.setReturnStatement(this.returnStatement); - reader.setWhereStatement(this.whereStatement); - reader.setName(this.name); - reader.setSaveState(this.saveState); - reader.setCurrentItemCount(this.currentItemCount); - reader.setMaxItemCount(this.maxItemCount); - - return reader; - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java deleted file mode 100644 index 1e4e334799..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data.builder; - -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.data.Neo4jItemWriter; -import org.springframework.util.Assert; - -/** - * A builder implementation for the {@link Neo4jItemWriter} - * - * @author Glenn Renfro - * @author Mahmoud Ben Hassine - * @since 4.0 - * @see Neo4jItemWriter - * @deprecated since 5.0 in favor of the item writer builder from ... - */ -@Deprecated -public class Neo4jItemWriterBuilder { - - private boolean delete = false; - - private SessionFactory sessionFactory; - - /** - * Boolean flag indicating whether the writer should save or delete the item at write - * time. - * @param delete true if write should delete item, false if item should be saved. - * Default is false. - * @return The current instance of the builder - * @see Neo4jItemWriter#setDelete(boolean) - */ - public Neo4jItemWriterBuilder delete(boolean delete) { - this.delete = delete; - - return this; - } - - /** - * Establish the session factory that will be used to create {@link Session} instances - * for interacting with Neo4j. - * @param sessionFactory sessionFactory to be used. - * @return The current instance of the builder - * @see Neo4jItemWriter#setSessionFactory(SessionFactory) - */ - public Neo4jItemWriterBuilder sessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - - return this; - } - - /** - * Validates and builds a {@link org.springframework.batch.item.data.Neo4jItemWriter}. - * @return a {@link Neo4jItemWriter} - */ - public Neo4jItemWriter build() { - Assert.notNull(sessionFactory, "sessionFactory is required."); - Neo4jItemWriter writer = new Neo4jItemWriter<>(); - writer.setDelete(this.delete); - writer.setSessionFactory(this.sessionFactory); - return writer; - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java index 2ae66e4388..265c6275c3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,36 +61,6 @@ public static String generateLimitSqlQuery(AbstractSqlPagingQueryProvider provid return sql.toString(); } - /** - * Generate SQL query string using a LIMIT clause - * @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation - * specifics - * @param remainingPageQuery is this query for the remaining pages (true) as opposed - * to the first page (false) - * @param limitClause the implementation specific limit clause to be used - * @return the generated query - * @deprecated as of v5.0 in favor of - * {@link #generateLimitGroupedSqlQuery(AbstractSqlPagingQueryProvider, java.lang.String)} - */ - @Deprecated - public static String generateLimitGroupedSqlQuery(AbstractSqlPagingQueryProvider provider, - boolean remainingPageQuery, String limitClause) { - StringBuilder sql = new StringBuilder(); - sql.append("SELECT * "); - sql.append(" FROM ("); - sql.append("SELECT ").append(provider.getSelectClause()); - sql.append(" FROM ").append(provider.getFromClause()); - sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); - buildGroupByClause(provider, sql); - sql.append(") AS MAIN_QRY "); - sql.append("WHERE "); - buildSortConditions(provider, sql); - sql.append(" ORDER BY ").append(buildSortClause(provider)); - sql.append(" ").append(limitClause); - - return sql.toString(); - } - /** * Generate SQL query string using a LIMIT clause * @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation @@ -136,34 +106,6 @@ public static String generateTopSqlQuery(AbstractSqlPagingQueryProvider provider return sql.toString(); } - /** - * Generate SQL query string using a TOP clause - * @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation - * specifics - * @param remainingPageQuery is this query for the remaining pages (true) as opposed - * to the first page (false) - * @param topClause the implementation specific top clause to be used - * @return the generated query - * @deprecated since v5.2 in favor of - * {@link #generateGroupedTopSqlQuery(AbstractSqlPagingQueryProvider, String)} - */ - @Deprecated - public static String generateGroupedTopSqlQuery(AbstractSqlPagingQueryProvider provider, boolean remainingPageQuery, - String topClause) { - StringBuilder sql = new StringBuilder(); - sql.append("SELECT ").append(topClause).append(" * FROM ("); - sql.append("SELECT ").append(provider.getSelectClause()); - sql.append(" FROM ").append(provider.getFromClause()); - sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); - buildGroupByClause(provider, sql); - sql.append(") AS MAIN_QRY "); - sql.append("WHERE "); - buildSortConditions(provider, sql); - sql.append(" ORDER BY ").append(buildSortClause(provider)); - - return sql.toString(); - } - /** * Generate SQL query string using a TOP clause * @param provider {@link AbstractSqlPagingQueryProvider} providing the implementation diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java deleted file mode 100644 index 00e0d04711..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2006-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.database.support; - -import org.springframework.util.StringUtils; - -/** - * Generic Paging Query Provider using standard SQL:2003 windowing functions. These - * features are supported by DB2, Oracle, SQL Server 2005, Sybase and Apache Derby version - * 10.4.1.3 - * - * @author Thomas Risberg - * @author Michael Minella - * @since 2.0 - * @deprecated since 5.2.1 with no replacement. Scheduled for removal in 6.0. - */ -@Deprecated(forRemoval = true) -public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvider { - - @Override - public String generateFirstPageQuery(int pageSize) { - StringBuilder sql = new StringBuilder(); - sql.append("SELECT * FROM ( "); - sql.append("SELECT ") - .append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); - sql.append("ROW_NUMBER() OVER (").append(getOverClause()); - sql.append(") AS ROW_NUMBER"); - sql.append(getOverSubstituteClauseStart()); - sql.append(" FROM ") - .append(getFromClause()) - .append(getWhereClause() == null ? "" : " WHERE " + getWhereClause()); - sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); - sql.append(getOverSubstituteClauseEnd()); - sql.append(") ") - .append(getSubQueryAlias()) - .append("WHERE ") - .append(extractTableAlias()) - .append("ROW_NUMBER <= ") - .append(pageSize); - sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this)); - - return sql.toString(); - } - - protected String getOrderedQueryAlias() { - return ""; - } - - protected Object getSubQueryAlias() { - return "AS TMP_SUB "; - } - - protected Object extractTableAlias() { - String alias = String.valueOf(getSubQueryAlias()); - if (StringUtils.hasText(alias) && alias.toUpperCase().startsWith("AS")) { - alias = alias.substring(3).trim() + "."; - } - return alias; - } - - @Override - public String generateRemainingPagesQuery(int pageSize) { - StringBuilder sql = new StringBuilder(); - sql.append("SELECT * FROM ( "); - sql.append("SELECT ") - .append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); - sql.append("ROW_NUMBER() OVER (").append(getOverClause()); - sql.append(") AS ROW_NUMBER"); - sql.append(getOverSubstituteClauseStart()); - sql.append(" FROM ").append(getFromClause()); - if (getWhereClause() != null) { - sql.append(" WHERE "); - sql.append(getWhereClause()); - } - - sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); - sql.append(getOverSubstituteClauseEnd()); - sql.append(") ") - .append(getSubQueryAlias()) - .append("WHERE ") - .append(extractTableAlias()) - .append("ROW_NUMBER <= ") - .append(pageSize); - sql.append(" AND "); - SqlPagingQueryUtils.buildSortConditions(this, sql); - sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this)); - - return sql.toString(); - } - - protected String getOverClause() { - StringBuilder sql = new StringBuilder(); - - sql.append(" ORDER BY ").append(buildSortClause(this)); - - return sql.toString(); - } - - protected String getOverSubstituteClauseStart() { - return ""; - } - - protected String getOverSubstituteClauseEnd() { - return ""; - } - - /** - * Generates ORDER BY attributes based on the sort keys. - * @param provider the paging query provider - * @return a String that can be appended to an ORDER BY clause. - */ - private String buildSortClause(AbstractSqlPagingQueryProvider provider) { - return SqlPagingQueryUtils.buildSortClause(provider.getSortKeysWithoutAliases()); - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java deleted file mode 100644 index cea6e890da..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.repeat.listener; - -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.RepeatListener; - -/** - * Empty method implementation of {@link RepeatListener}. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @deprecated as of v5.0 in favor of the default methods in {@link RepeatListener}. - */ -@Deprecated -public class RepeatListenerSupport implements RepeatListener { - - @Override - public void before(RepeatContext context) { - } - - @Override - public void after(RepeatContext context, RepeatStatus result) { - } - - @Override - public void close(RepeatContext context) { - } - - @Override - public void onError(RepeatContext context, Throwable e) { - } - - @Override - public void open(RepeatContext context) { - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java index 44dba5b449..005fefe4f7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,25 +59,6 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { private TaskExecutor taskExecutor = new SyncTaskExecutor(); - /** - * Public setter for the throttle limit. The throttle limit is the largest number of - * concurrent tasks that can be executing at one time - if a new task arrives and the - * throttle limit is breached we wait for one of the executing tasks to finish before - * submitting the new one to the {@link TaskExecutor}. Default value is - * {@link #DEFAULT_THROTTLE_LIMIT}. N.B. when used with a thread pooled - * {@link TaskExecutor} the thread pool might prevent the throttle limit actually - * being reached (so make the core pool size larger than the throttle limit if - * possible). - * @param throttleLimit the throttleLimit to set. - * @deprecated since 5.0, scheduled for removal in 6.0. Use a pooled - * {@link TaskExecutor} implemenation with a limited capacity of its task queue - * instead. - */ - @Deprecated(since = "5.0", forRemoval = true) - public void setThrottleLimit(int throttleLimit) { - this.throttleLimit = throttleLimit; - } - /** * Setter for task executor to be used to run the individual item callbacks. * @param taskExecutor a TaskExecutor diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java deleted file mode 100644 index ea2ff9bacf..0000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2006-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Helper class that sets up a System property with a default value. A System property is - * created with the specified key name, and default value (i.e. if the property already - * exists it is not changed). - * - * @author Dave Syer - * @deprecated since 5.2 with no replacement. - */ -@Deprecated(since = "5.2.0", forRemoval = true) -public class SystemPropertyInitializer implements InitializingBean { - - /** - * Name of system property used by default. - */ - public static final String ENVIRONMENT = "org.springframework.batch.support.SystemPropertyInitializer.ENVIRONMENT"; - - private String keyName = ENVIRONMENT; - - private String defaultValue; - - /** - * Set the key name for the System property that is created. Defaults to - * {@link #ENVIRONMENT}. - * @param keyName the key name to set - */ - public void setKeyName(String keyName) { - this.keyName = keyName; - } - - /** - * Mandatory property specifying the default value of the System property. - * @param defaultValue the default value to set - */ - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - /** - * Sets the System property with the provided name and default value. - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(defaultValue != null || System.getProperty(keyName) != null, - "Either a default value must be specified or the value should already be set for System property: " - + keyName); - System.setProperty(keyName, System.getProperty(keyName, defaultValue)); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java index 55919f242d..1ed55109af 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 the original author or authors. + * Copyright 2013-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -199,7 +199,7 @@ void testWriteTransactionReadOnly() { @Test void testRemoveNoObjectIdNoCollection() throws Exception { - writer.setDelete(true); + writer.setMode(Mode.REMOVE); Chunk items = Chunk.of(new Item("Foo"), new Item("Bar")); writer.write(items); @@ -210,7 +210,7 @@ void testRemoveNoObjectIdNoCollection() throws Exception { @Test void testRemoveNoObjectIdWithCollection() throws Exception { - writer.setDelete(true); + writer.setMode(Mode.REMOVE); Chunk items = Chunk.of(new Item("Foo"), new Item("Bar")); writer.setCollection("collection"); @@ -222,7 +222,7 @@ void testRemoveNoObjectIdWithCollection() throws Exception { @Test void testRemoveNoTransactionNoCollection() throws Exception { - writer.setDelete(true); + writer.setMode(Mode.REMOVE); Chunk items = Chunk.of(new Item(1), new Item(2)); writer.write(items); @@ -233,7 +233,7 @@ void testRemoveNoTransactionNoCollection() throws Exception { @Test void testRemoveNoTransactionWithCollection() throws Exception { - writer.setDelete(true); + writer.setMode(Mode.REMOVE); Chunk items = Chunk.of(new Item(1), new Item(2)); writer.setCollection("collection"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java deleted file mode 100644 index 34d2791810..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2013-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.data; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.when; - -@SuppressWarnings("deprecation") -@ExtendWith(MockitoExtension.class) -class Neo4jItemReaderTests { - - @Mock - private Iterable result; - - @Mock - private SessionFactory sessionFactory; - - @Mock - private Session session; - - private Neo4jItemReader buildSessionBasedReader() throws Exception { - Neo4jItemReader reader = new Neo4jItemReader<>(); - - reader.setSessionFactory(this.sessionFactory); - reader.setTargetType(String.class); - reader.setStartStatement("n=node(*)"); - reader.setReturnStatement("*"); - reader.setOrderByStatement("n.age"); - reader.setPageSize(50); - reader.afterPropertiesSet(); - - return reader; - } - - @Test - void testAfterPropertiesSet() throws Exception { - - Neo4jItemReader reader = new Neo4jItemReader<>(); - - Exception exception = assertThrows(IllegalStateException.class, reader::afterPropertiesSet); - assertEquals("A SessionFactory is required", exception.getMessage()); - - reader.setSessionFactory(this.sessionFactory); - - exception = assertThrows(IllegalStateException.class, reader::afterPropertiesSet); - assertEquals("The type to be returned is required", exception.getMessage()); - - reader.setTargetType(String.class); - - exception = assertThrows(IllegalStateException.class, reader::afterPropertiesSet); - assertEquals("A START statement is required", exception.getMessage()); - - reader.setStartStatement("n=node(*)"); - - exception = assertThrows(IllegalStateException.class, reader::afterPropertiesSet); - assertEquals("A RETURN statement is required", exception.getMessage()); - - reader.setReturnStatement("n.name, n.phone"); - - exception = assertThrows(IllegalStateException.class, reader::afterPropertiesSet); - assertEquals("A ORDER BY statement is required", exception.getMessage()); - - reader.setOrderByStatement("n.age"); - reader.afterPropertiesSet(); - - reader = new Neo4jItemReader<>(); - reader.setSessionFactory(this.sessionFactory); - reader.setTargetType(String.class); - reader.setStartStatement("n=node(*)"); - reader.setReturnStatement("n.name, n.phone"); - reader.setOrderByStatement("n.age"); - - reader.afterPropertiesSet(); - } - - @Test - void testNullResultsWithSession() throws Exception { - - Neo4jItemReader itemReader = buildSessionBasedReader(); - - ArgumentCaptor query = ArgumentCaptor.forClass(String.class); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(eq(String.class), query.capture(), isNull())).thenReturn(null); - - assertFalse(itemReader.doPageRead().hasNext()); - assertEquals("START n=node(*) RETURN * ORDER BY n.age SKIP 0 LIMIT 50", query.getValue()); - } - - @Test - void testNoResultsWithSession() throws Exception { - Neo4jItemReader itemReader = buildSessionBasedReader(); - ArgumentCaptor query = ArgumentCaptor.forClass(String.class); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(eq(String.class), query.capture(), isNull())).thenReturn(result); - when(result.iterator()).thenReturn(Collections.emptyIterator()); - - assertFalse(itemReader.doPageRead().hasNext()); - assertEquals("START n=node(*) RETURN * ORDER BY n.age SKIP 0 LIMIT 50", query.getValue()); - } - - @Test - void testResultsWithMatchAndWhereWithSession() throws Exception { - Neo4jItemReader itemReader = buildSessionBasedReader(); - itemReader.setMatchStatement("n -- m"); - itemReader.setWhereStatement("has(n.name)"); - itemReader.setReturnStatement("m"); - itemReader.afterPropertiesSet(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, - "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) - .thenReturn(result); - when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); - - assertTrue(itemReader.doPageRead().hasNext()); - } - - @Test - void testResultsWithMatchAndWhereWithParametersWithSession() throws Exception { - Neo4jItemReader itemReader = buildSessionBasedReader(); - Map params = new HashMap<>(); - params.put("foo", "bar"); - itemReader.setParameterValues(params); - itemReader.setMatchStatement("n -- m"); - itemReader.setWhereStatement("has(n.name)"); - itemReader.setReturnStatement("m"); - itemReader.afterPropertiesSet(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, - "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", params)) - .thenReturn(result); - when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); - - assertTrue(itemReader.doPageRead().hasNext()); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java deleted file mode 100644 index 2a9650f601..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2013-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.data; - -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.Chunk; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -@SuppressWarnings("deprecation") -@MockitoSettings(strictness = Strictness.LENIENT) -class Neo4jItemWriterTests { - - private Neo4jItemWriter writer; - - @Mock - private SessionFactory sessionFactory; - - @Mock - private Session session; - - @Test - void testAfterPropertiesSet() throws Exception { - - writer = new Neo4jItemWriter<>(); - - Exception exception = assertThrows(IllegalStateException.class, writer::afterPropertiesSet); - assertEquals("A SessionFactory is required", exception.getMessage()); - - writer.setSessionFactory(this.sessionFactory); - - writer.afterPropertiesSet(); - - writer = new Neo4jItemWriter<>(); - - writer.setSessionFactory(this.sessionFactory); - - writer.afterPropertiesSet(); - } - - @Test - void testWriteNoItemsWithSession() throws Exception { - writer = new Neo4jItemWriter<>(); - - writer.setSessionFactory(this.sessionFactory); - writer.afterPropertiesSet(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - writer.write(new Chunk<>()); - - verifyNoInteractions(this.session); - } - - @Test - void testWriteItemsWithSession() throws Exception { - writer = new Neo4jItemWriter<>(); - - writer.setSessionFactory(this.sessionFactory); - writer.afterPropertiesSet(); - - Chunk items = new Chunk<>(); - items.add("foo"); - items.add("bar"); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - writer.write(items); - - verify(this.session).save("foo"); - verify(this.session).save("bar"); - } - - @Test - void testDeleteItemsWithSession() throws Exception { - writer = new Neo4jItemWriter<>(); - - writer.setSessionFactory(this.sessionFactory); - writer.afterPropertiesSet(); - - Chunk items = new Chunk<>(); - items.add("foo"); - items.add("bar"); - - writer.setDelete(true); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - writer.write(items); - - verify(this.session).delete("foo"); - verify(this.session).delete("bar"); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java index 699dd40f57..13b4f58bf0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 the original author or authors. + * Copyright 2017-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -112,7 +112,9 @@ void testWriteToCollection() throws Exception { @Test void testDelete() throws Exception { - MongoItemWriter writer = new MongoItemWriterBuilder().template(this.template).delete(true).build(); + MongoItemWriter writer = new MongoItemWriterBuilder().template(this.template) + .mode(MongoItemWriter.Mode.REMOVE) + .build(); writer.write(this.removeItems); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java deleted file mode 100644 index 08d7dacc57..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2017-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data.builder; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.data.Neo4jItemReader; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; - -/** - * @author Glenn Renfro - */ -@SuppressWarnings("deprecation") -@ExtendWith(MockitoExtension.class) -class Neo4jItemReaderBuilderTests { - - @Mock - private Iterable result; - - @Mock - private SessionFactory sessionFactory; - - @Mock - private Session session; - - @Test - void testFullyQualifiedItemReader() throws Exception { - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m") - .build(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, - "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) - .thenReturn(result); - when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); - - assertEquals("foo", itemReader.read(), "The expected value was not returned by reader."); - assertEquals("bar", itemReader.read(), "The expected value was not returned by reader."); - assertEquals("baz", itemReader.read(), "The expected value was not returned by reader."); - } - - @Test - void testCurrentSize() throws Exception { - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .returnStatement("m") - .currentItemCount(0) - .maxItemCount(1) - .build(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, "START n=node(*) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) - .thenReturn(result); - when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); - - assertEquals("foo", itemReader.read(), "The expected value was not returned by reader."); - assertNull(itemReader.read(), "The expected value was not should be null."); - } - - @Test - void testResultsWithMatchAndWhereWithParametersWithSession() throws Exception { - Map params = new HashMap<>(); - params.put("foo", "bar"); - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("foo") - .parameterValues(params) - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m") - .build(); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, - "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", params)) - .thenReturn(result); - when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); - - assertEquals("foo", itemReader.read(), "The expected value was not returned by reader."); - } - - @Test - void testNoSessionFactory() { - var builder = new Neo4jItemReaderBuilder().targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("bar"); - Exception exception = assertThrows(IllegalArgumentException.class, builder::build); - assertEquals("sessionFactory is required.", exception.getMessage()); - } - - @Test - void testZeroPageSize() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(0) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "pageSize must be greater than zero"); - } - - @Test - void testZeroMaxItemCount() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(5) - .maxItemCount(0) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "maxItemCount must be greater than zero"); - } - - @Test - void testCurrentItemCountGreaterThanMaxItemCount() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(5) - .maxItemCount(5) - .currentItemCount(6) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "maxItemCount must be greater than currentItemCount"); - } - - @Test - void testNullName() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50), "A name is required when saveState is set to true"); - - // tests that name is not required if saveState is set to false. - new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .saveState(false) - .pageSize(50) - .build(); - } - - @Test - void testNullTargetType() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "targetType is required."); - } - - @Test - void testNullStartStatement() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "startStatement is required."); - } - - @Test - void testNullReturnStatement() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)"), "returnStatement is required."); - } - - @Test - void testNullOrderByStatement() { - validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), "orderByStatement is required."); - } - - private void validateExceptionMessage(Neo4jItemReaderBuilder builder, String message) { - Exception exception = assertThrows(IllegalArgumentException.class, builder::build); - assertEquals(message, exception.getMessage()); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java deleted file mode 100644 index 3f6629483c..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.data.builder; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.neo4j.ogm.session.Session; -import org.neo4j.ogm.session.SessionFactory; - -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.data.Neo4jItemWriter; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * @author Glenn Renfro - * @author Mahmoud Ben Hassine - */ -@SuppressWarnings("deprecation") -@ExtendWith(MockitoExtension.class) -class Neo4jItemWriterBuilderTests { - - @Mock - private SessionFactory sessionFactory; - - @Mock - private Session session; - - @Test - void testBasicWriter() throws Exception { - Neo4jItemWriter writer = new Neo4jItemWriterBuilder().sessionFactory(this.sessionFactory) - .build(); - Chunk items = new Chunk<>(); - items.add("foo"); - items.add("bar"); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - writer.write(items); - - verify(this.session).save("foo"); - verify(this.session).save("bar"); - verify(this.session, never()).delete("foo"); - verify(this.session, never()).delete("bar"); - } - - @Test - void testBasicDelete() throws Exception { - Neo4jItemWriter writer = new Neo4jItemWriterBuilder().delete(true) - .sessionFactory(this.sessionFactory) - .build(); - Chunk items = new Chunk<>(); - items.add("foo"); - items.add("bar"); - - when(this.sessionFactory.openSession()).thenReturn(this.session); - writer.write(items); - - verify(this.session).delete("foo"); - verify(this.session).delete("bar"); - verify(this.session, never()).save("foo"); - verify(this.session, never()).save("bar"); - } - - @Test - void testNoSessionFactory() { - Exception exception = assertThrows(IllegalArgumentException.class, - () -> new Neo4jItemWriterBuilder().build()); - assertEquals("sessionFactory is required.", exception.getMessage()); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java deleted file mode 100644 index cd58aecfb9..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2006-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database.support; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * @author Thomas Risberg - * @author Michael Minella - */ -class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests { - - @SuppressWarnings("removal") - SqlWindowingPagingQueryProviderTests() { - pagingQueryProvider = new SqlWindowingPagingQueryProvider(); - } - - @Test - @Override - void testGenerateFirstPageQuery() { - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - assertEquals(sql, s); - } - - @Test - @Override - void testGenerateRemainingPagesQuery() { - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - assertEquals(sql, s); - } - - @Test - @Override - void testGenerateFirstPageQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - assertEquals(sql, s); - } - - @Test - @Override - void testGenerateRemainingPagesQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - assertEquals(sql, s); - } - - @Override - String getFirstPageSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY name ASC, id DESC"; - } - - @Override - String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java index 5d6dd52924..89a393ae49 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -159,7 +159,6 @@ void testThrottleLimit() { SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); taskExecutor.setConcurrencyLimit(300); template.setTaskExecutor(taskExecutor); - template.setThrottleLimit(throttleLimit); String threadName = Thread.currentThread().getName(); Set threadNames = ConcurrentHashMap.newKeySet(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java index cb39231a65..47dd4e892f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; @@ -35,7 +33,6 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; -import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** @@ -54,8 +51,6 @@ class TaskExecutorRepeatTemplateBulkAsynchronousTests { private int total = 1000; - private int throttleLimit = 30; - private volatile int early = Integer.MAX_VALUE; private volatile int error = Integer.MAX_VALUE; @@ -77,7 +72,6 @@ void setUp() { threadPool.setQueueCapacity(0); threadPool.afterPropertiesSet(); template.setTaskExecutor(threadPool); - template.setThrottleLimit(throttleLimit); items = Collections.synchronizedList(new ArrayList<>()); @@ -117,102 +111,6 @@ void tearDown() { threadPool.destroy(); } - @Test - void testThrottleLimit() { - - template.iterate(callback); - int frequency = Collections.frequency(items, null); - assertEquals(total, items.size() - frequency); - assertTrue(frequency > 1); - assertTrue(frequency <= throttleLimit + 1); - - } - - @Test - void testThrottleLimitEarlyFinish() { - - early = 2; - - template.iterate(callback); - int frequency = Collections.frequency(items, null); - assertEquals(total, items.size() - frequency); - assertTrue(frequency > 1); - assertTrue(frequency <= throttleLimit + 1); - - } - - @Test - void testThrottleLimitEarlyFinishThreadStarvation() { - - early = 2; - ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); - // Set the concurrency limit below the throttle limit for possible - // starvation condition - taskExecutor.setMaxPoolSize(20); - taskExecutor.setCorePoolSize(10); - taskExecutor.setQueueCapacity(0); - // This is the most sensible setting, otherwise the bookkeeping in - // ResultHolderResultQueue gets out of whack when tasks are aborted. - taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); - taskExecutor.afterPropertiesSet(); - template.setTaskExecutor(taskExecutor); - - template.iterate(callback); - int frequency = Collections.frequency(items, null); - // Extra tasks will be submitted before the termination is detected - assertEquals(total, items.size() - frequency); - assertTrue(frequency <= throttleLimit + 1); - - taskExecutor.destroy(); - - } - - @Test - void testThrottleLimitEarlyFinishOneThread() { - - early = 4; - SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); - taskExecutor.setConcurrencyLimit(1); - - // This is kind of slow with only one thread, so reduce size: - throttleLimit = 10; - total = 20; - - template.setThrottleLimit(throttleLimit); - template.setTaskExecutor(taskExecutor); - - template.iterate(callback); - int frequency = Collections.frequency(items, null); - assertEquals(total, items.size() - frequency); - assertTrue(frequency <= throttleLimit + 1); - - } - - @Test - void testThrottleLimitWithEarlyCompletion() { - - early = 2; - template.setCompletionPolicy(new SimpleCompletionPolicy(10)); - - template.iterate(callback); - int frequency = Collections.frequency(items, null); - assertEquals(10, items.size() - frequency); - assertEquals(0, frequency); - - } - - @Test - void testThrottleLimitWithError() { - - error = 50; - - Exception exception = assertThrows(Exception.class, () -> template.iterate(callback)); - assertEquals("Planned", exception.getMessage()); - int frequency = Collections.frequency(items, null); - assertEquals(0, frequency); - - } - @Test void testErrorThrownByCallback() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java index c9245d7174..32926ce554 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,9 @@ package org.springframework.batch.repeat.support; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - -import org.junit.jupiter.api.Test; - /** * @author Dave Syer + * @author Mahmoud Ben Hassine */ public class TaskExecutorRepeatTemplateTests extends SimpleRepeatTemplateTests { @@ -30,10 +27,4 @@ public RepeatTemplate getRepeatTemplate() { return new TaskExecutorRepeatTemplate(); } - @Test - void testSetThrottleLimit() { - // no check for illegal values - assertDoesNotThrow(() -> new TaskExecutorRepeatTemplate().setThrottleLimit(-1)); - } - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java deleted file mode 100644 index f35d707858..0000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2006-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * @author Dave Syer - * - */ -class SystemPropertyInitializerTests { - - private static final String SIMPLE_NAME = SystemPropertyInitializerTests.class.getSimpleName(); - - private final SystemPropertyInitializer initializer = new SystemPropertyInitializer(); - - @BeforeEach - @AfterEach - void initializeProperty() { - System.clearProperty(SystemPropertyInitializer.ENVIRONMENT); - System.clearProperty(SIMPLE_NAME); - } - - @Test - void testSetKeyName() throws Exception { - initializer.setKeyName(SIMPLE_NAME); - System.setProperty(SIMPLE_NAME, "foo"); - initializer.afterPropertiesSet(); - assertEquals("foo", System.getProperty(SIMPLE_NAME)); - } - - @Test - void testSetDefaultValue() throws Exception { - initializer.setDefaultValue("foo"); - initializer.afterPropertiesSet(); - assertEquals("foo", System.getProperty(SystemPropertyInitializer.ENVIRONMENT)); - } - - @Test - void testNoDefaultValue() { - assertThrows(IllegalStateException.class, initializer::afterPropertiesSet); - } - -} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java index 4d033b61cf..dce57ad57c 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the original author or authors. + * Copyright 2019-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,17 +82,6 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui private long throttleLimit = DEFAULT_THROTTLE_LIMIT; - /** - * Create a new {@link RemoteChunkingManagerStepBuilder}. - * @param stepName name of the manager step - * @deprecated use - * {@link RemoteChunkingManagerStepBuilder#RemoteChunkingManagerStepBuilder(String, JobRepository)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public RemoteChunkingManagerStepBuilder(String stepName) { - super(new StepBuilder(stepName)); - } - /** * Create a new {@link RemoteChunkingManagerStepBuilder}. * @param stepName name of the manager step @@ -228,21 +217,6 @@ public RemoteChunkingManagerStepBuilder reader(ItemReader rea return this; } - /** - * Set the job repository - * @param jobRepository the repository to set - * @return this to enable fluent chaining - * @deprecated use - * {@link RemoteChunkingManagerStepBuilder#RemoteChunkingManagerStepBuilder(String, JobRepository)} - */ - @Override - @SuppressWarnings("removal") - @Deprecated(since = "5.1", forRemoval = true) - public RemoteChunkingManagerStepBuilder repository(JobRepository jobRepository) { - super.repository(jobRepository); - return this; - } - @Override public RemoteChunkingManagerStepBuilder transactionManager(PlatformTransactionManager transactionManager) { super.transactionManager(transactionManager); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java index 9759b4bc13..fd9a24f66c 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 the original author or authors. + * Copyright 2019-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,17 +78,6 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { private long timeout = DEFAULT_TIMEOUT; - /** - * Create a new {@link RemotePartitioningManagerStepBuilder}. - * @param stepName name of the manager step - * @deprecated use - * {@link RemotePartitioningManagerStepBuilder#RemotePartitioningManagerStepBuilder(String, JobRepository)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public RemotePartitioningManagerStepBuilder(String stepName) { - super(new StepBuilder(stepName)); - } - /** * Create a new {@link RemotePartitioningManagerStepBuilder}. * @param stepName name of the manager step @@ -243,21 +232,6 @@ private boolean isPolling() { return this.inputChannel == null; } - /** - * Set the job repository - * @param jobRepository the repository to set - * @return this to enable fluent chaining - * @deprecated use - * {@link RemotePartitioningManagerStepBuilder#RemotePartitioningManagerStepBuilder(String, JobRepository)} - */ - @Override - @SuppressWarnings("removal") - @Deprecated(since = "5.1", forRemoval = true) - public RemotePartitioningManagerStepBuilder repository(JobRepository jobRepository) { - super.repository(jobRepository); - return this; - } - @Override public RemotePartitioningManagerStepBuilder partitioner(String workerStepName, Partitioner partitioner) { super.partitioner(workerStepName, partitioner); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java index 16fda82326..a0fa3b9f11 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 the original author or authors. + * Copyright 2018-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,17 +80,6 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { private BeanFactory beanFactory; - /** - * Initialize a step builder for a step with the given name. - * @param name the name of the step - * @deprecated use - * {@link RemotePartitioningWorkerStepBuilder#RemotePartitioningWorkerStepBuilder(String, JobRepository)} - */ - @Deprecated(since = "5.0", forRemoval = true) - public RemotePartitioningWorkerStepBuilder(String name) { - super(name); - } - /** * Initialize a step builder for a step with the given name. * @param name the name of the step @@ -157,21 +146,6 @@ public RemotePartitioningWorkerStepBuilder beanFactory(BeanFactory beanFactory) return this; } - /** - * Set the job repository - * @param jobRepository the repository to set - * @return this to enable fluent chaining - * @deprecated use - * {@link RemotePartitioningWorkerStepBuilder#RemotePartitioningWorkerStepBuilder(String, JobRepository)} - */ - @Override - @SuppressWarnings("removal") - @Deprecated(since = "5.1", forRemoval = true) - public RemotePartitioningWorkerStepBuilder repository(JobRepository jobRepository) { - super.repository(jobRepository); - return this; - } - @Override public RemotePartitioningWorkerStepBuilder startLimit(int startLimit) { super.startLimit(startLimit); @@ -196,39 +170,18 @@ public RemotePartitioningWorkerStepBuilder allowStartIfComplete(boolean allowSta return this; } - @Deprecated(since = "5.0", forRemoval = true) - @Override - public TaskletStepBuilder tasklet(Tasklet tasklet) { - configureWorkerIntegrationFlow(); - return super.tasklet(tasklet); - } - @Override public TaskletStepBuilder tasklet(Tasklet tasklet, PlatformTransactionManager transactionManager) { configureWorkerIntegrationFlow(); return super.tasklet(tasklet, transactionManager); } - @Deprecated(since = "5.0", forRemoval = true) - @Override - public SimpleStepBuilder chunk(int chunkSize) { - configureWorkerIntegrationFlow(); - return super.chunk(chunkSize); - } - @Override public SimpleStepBuilder chunk(int chunkSize, PlatformTransactionManager transactionManager) { configureWorkerIntegrationFlow(); return super.chunk(chunkSize, transactionManager); } - @Deprecated(since = "5.0", forRemoval = true) - @Override - public SimpleStepBuilder chunk(CompletionPolicy completionPolicy) { - configureWorkerIntegrationFlow(); - return super.chunk(completionPolicy); - } - @Override public SimpleStepBuilder chunk(CompletionPolicy completionPolicy, PlatformTransactionManager transactionManager) { diff --git a/spring-batch-samples/README.md b/spring-batch-samples/README.md index 770c7fd938..4b334cf8ee 100644 --- a/spring-batch-samples/README.md +++ b/spring-batch-samples/README.md @@ -603,7 +603,7 @@ class without any argument to start the sample. ### MongoDB sample This sample is a showcase of MongoDB support in Spring Batch. It copies data from -an input collection to an output collection using `MongoItemReader` and `MongoItemWriter`. +an input collection to an output collection using `MongoPagingItemReader` and `MongoItemWriter`. To run the sample, you need to have a MongoDB server up and running on `localhost:27017` (you can change these defaults in `mongodb-sample.properties`). If you use docker, diff --git a/spring-batch-samples/src/main/resources/data-source-context.xml b/spring-batch-samples/src/main/resources/data-source-context.xml index 39c1506bda..8f17365d1c 100644 --- a/spring-batch-samples/src/main/resources/data-source-context.xml +++ b/spring-batch-samples/src/main/resources/data-source-context.xml @@ -25,5 +25,4 @@ - diff --git a/spring-batch-samples/src/main/resources/org/springframework/batch/samples/misc/jmx/adhoc-job-launcher-context.xml b/spring-batch-samples/src/main/resources/org/springframework/batch/samples/misc/jmx/adhoc-job-launcher-context.xml index efbc83b8d5..a94273a433 100644 --- a/spring-batch-samples/src/main/resources/org/springframework/batch/samples/misc/jmx/adhoc-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/org/springframework/batch/samples/misc/jmx/adhoc-job-launcher-context.xml @@ -11,13 +11,13 @@ - + + p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager"/> - + + p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager"/> Date: Tue, 29 Apr 2025 12:00:58 +0200 Subject: [PATCH 005/182] Rearrange methods in JobExplorer/JobRepository APIs --- .../batch/core/explore/JobExplorer.java | 122 +++++++++++------- .../batch/core/repository/JobRepository.java | 98 ++++++++------ 2 files changed, 128 insertions(+), 92 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java index 85c69655f9..f10a5fa30e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,25 @@ */ public interface JobExplorer { + /* + * =================================================================================== + * Job operations + * =================================================================================== + */ + + /** + * Query the repository for all unique {@link JobInstance} names (sorted + * alphabetically). + * @return the list of job names that have been executed. + */ + List getJobNames(); + + /* + * =================================================================================== + * Job instance operations + * =================================================================================== + */ + /** * Fetch {@link JobInstance} values in descending order of creation (and, therefore, * usually, of first execution). @@ -50,6 +69,16 @@ public interface JobExplorer { */ List getJobInstances(String jobName, int start, int count); + /** + * Fetch {@link JobInstance} values in descending order of creation (and, therefore, + * usually of first execution) with a 'like' or wildcard criteria. + * @param jobName The name of the job for which to query. + * @param start The start index of the instances to return. + * @param count The maximum number of instances to return. + * @return a list of {@link JobInstance} for the requested job name. + */ + List findJobInstancesByJobName(String jobName, int start, int count); + /** * Find the last job instance, by ID, for the given job. * @param jobName The name of the job. @@ -62,31 +91,6 @@ default JobInstance getLastJobInstance(String jobName) { throw new UnsupportedOperationException(); } - /** - * Retrieve a {@link JobExecution} by its ID. The complete object graph for this - * execution should be returned (unless otherwise indicated), including the parent - * {@link JobInstance} and associated {@link ExecutionContext} and - * {@link StepExecution} instances (also including their execution contexts). - * @param executionId The job execution ID. - * @return the {@link JobExecution} that has this ID or {@code null} if not found. - */ - @Nullable - JobExecution getJobExecution(@Nullable Long executionId); - - /** - * Retrieve a {@link StepExecution} by its ID and parent {@link JobExecution} ID. The - * execution context for the step should be available in the result, and the parent - * job execution should have its primitive properties, but it may not contain the job - * instance information. - * @param jobExecutionId The parent job execution ID. - * @param stepExecutionId The step execution ID. - * @return the {@link StepExecution} that has this ID or {@code null} if not found. - * - * @see #getJobExecution(Long) - */ - @Nullable - StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable Long stepExecutionId); - /** * @param instanceId {@link Long} The ID for the {@link JobInstance} to obtain. * @return the {@code JobInstance} that has this ID, or {@code null} if not found. @@ -107,6 +111,34 @@ default JobInstance getJobInstance(String jobName, JobParameters jobParameters) throw new UnsupportedOperationException(); } + /** + * Query the repository for the number of unique {@link JobInstance} objects + * associated with the supplied job name. + * @param jobName The name of the job for which to query. + * @return the number of {@link JobInstance}s that exist within the associated job + * repository. + * @throws NoSuchJobException thrown when there is no {@link JobInstance} for the + * jobName specified. + */ + long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException; + + /* + * =================================================================================== + * Job execution operations + * =================================================================================== + */ + + /** + * Retrieve a {@link JobExecution} by its ID. The complete object graph for this + * execution should be returned (unless otherwise indicated), including the parent + * {@link JobInstance} and associated {@link ExecutionContext} and + * {@link StepExecution} instances (also including their execution contexts). + * @param executionId The job execution ID. + * @return the {@link JobExecution} that has this ID or {@code null} if not found. + */ + @Nullable + JobExecution getJobExecution(@Nullable Long executionId); + /** * Retrieve job executions by their job instance. The corresponding step executions * may not be fully hydrated (for example, their execution context may be missing), @@ -142,32 +174,24 @@ default JobExecution getLastJobExecution(JobInstance jobInstance) { */ Set findRunningJobExecutions(@Nullable String jobName); - /** - * Query the repository for all unique {@link JobInstance} names (sorted - * alphabetically). - * @return the list of job names that have been executed. - */ - List getJobNames(); - - /** - * Fetch {@link JobInstance} values in descending order of creation (and, therefore, - * usually of first execution) with a 'like' or wildcard criteria. - * @param jobName The name of the job for which to query. - * @param start The start index of the instances to return. - * @param count The maximum number of instances to return. - * @return a list of {@link JobInstance} for the requested job name. + /* + * =================================================================================== + * Step execution operations + * =================================================================================== */ - List findJobInstancesByJobName(String jobName, int start, int count); /** - * Query the repository for the number of unique {@link JobInstance} objects - * associated with the supplied job name. - * @param jobName The name of the job for which to query. - * @return the number of {@link JobInstance}s that exist within the associated job - * repository. - * @throws NoSuchJobException thrown when there is no {@link JobInstance} for the - * jobName specified. + * Retrieve a {@link StepExecution} by its ID and parent {@link JobExecution} ID. The + * execution context for the step should be available in the result, and the parent + * job execution should have its primitive properties, but it may not contain the job + * instance information. + * @param jobExecutionId The parent job execution ID. + * @param stepExecutionId The step execution ID. + * @return the {@link StepExecution} that has this ID or {@code null} if not found. + * + * @see #getJobExecution(Long) */ - long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException; + @Nullable + StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable Long stepExecutionId); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java index b8db9253b2..b4c7d3da88 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,12 @@ */ public interface JobRepository { + /* + * =================================================================================== + * Read only operations + * =================================================================================== + */ + /** * Retrieve the names of all job instances sorted alphabetically - i.e. jobs that have * ever been executed. @@ -74,6 +80,28 @@ default List findJobInstancesByName(String jobName, int start, int return Collections.emptyList(); } + /** + * Check if an instance of this job already exists with the parameters provided. + * @param jobName the name of the job + * @param jobParameters the parameters to match + * @return true if a {@link JobInstance} already exists for this job name and job + * parameters + */ + boolean isJobInstanceExists(String jobName, JobParameters jobParameters); + + /** + * @param jobName {@link String} name of the job. + * @param jobParameters {@link JobParameters} parameters for the job instance. + * @return the {@link JobInstance} with the given name and parameters, or + * {@code null}. + * + * @since 5.0 + */ + @Nullable + default JobInstance getJobInstance(String jobName, JobParameters jobParameters) { + throw new UnsupportedOperationException(); + } + /** * Return all {@link JobExecution}s for given {@link JobInstance}, sorted backwards by * creation order (so the first element is the most recent). @@ -86,13 +114,33 @@ default List findJobExecutions(JobInstance jobInstance) { } /** - * Check if an instance of this job already exists with the parameters provided. - * @param jobName the name of the job - * @param jobParameters the parameters to match - * @return true if a {@link JobInstance} already exists for this job name and job - * parameters + * @param jobName the name of the job that might have run + * @param jobParameters parameters identifying the {@link JobInstance} + * @return the last execution of job if exists, null otherwise + */ + @Nullable + JobExecution getLastJobExecution(String jobName, JobParameters jobParameters); + + /** + * @param jobInstance {@link JobInstance} instance containing the step executions. + * @param stepName the name of the step execution that might have run. + * @return the last execution of step for the given job instance. + */ + @Nullable + StepExecution getLastStepExecution(JobInstance jobInstance, String stepName); + + /** + * @param jobInstance {@link JobInstance} instance containing the step executions. + * @param stepName the name of the step execution that might have run. + * @return the execution count of the step within the given job instance. + */ + long getStepExecutionCount(JobInstance jobInstance, String stepName); + + /* + * =================================================================================== + * Write/Update operations + * =================================================================================== */ - boolean isJobInstanceExists(String jobName, JobParameters jobParameters); /** * Create a new {@link JobInstance} with the name and job parameters provided. @@ -187,42 +235,6 @@ JobExecution createJobExecution(String jobName, JobParameters jobParameters) */ void updateExecutionContext(JobExecution jobExecution); - /** - * @param jobName {@link String} name of the job. - * @param jobParameters {@link JobParameters} parameters for the job instance. - * @return the {@link JobInstance} with the given name and parameters, or - * {@code null}. - * - * @since 5.0 - */ - @Nullable - default JobInstance getJobInstance(String jobName, JobParameters jobParameters) { - throw new UnsupportedOperationException(); - } - - /** - * @param jobInstance {@link JobInstance} instance containing the step executions. - * @param stepName the name of the step execution that might have run. - * @return the last execution of step for the given job instance. - */ - @Nullable - StepExecution getLastStepExecution(JobInstance jobInstance, String stepName); - - /** - * @param jobInstance {@link JobInstance} instance containing the step executions. - * @param stepName the name of the step execution that might have run. - * @return the execution count of the step within the given job instance. - */ - long getStepExecutionCount(JobInstance jobInstance, String stepName); - - /** - * @param jobName the name of the job that might have run - * @param jobParameters parameters identifying the {@link JobInstance} - * @return the last execution of job if exists, null otherwise - */ - @Nullable - JobExecution getLastJobExecution(String jobName, JobParameters jobParameters); - /** * Delete the step execution along with its execution context. * @param stepExecution the step execution to delete From bf53794d6a1f1ab08d3fbc18cc40e1048e376e9c Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Tue, 29 Apr 2025 12:18:27 +0200 Subject: [PATCH 006/182] Deprecate redundant methods in JobExplorer/JobInstanceDao APIs Resolves #4821 --- .../batch/core/explore/JobExplorer.java | 3 ++ .../explore/support/SimpleJobExplorer.java | 7 ++++- .../repository/dao/JdbcJobInstanceDao.java | 31 ++++--------------- .../core/repository/dao/JobInstanceDao.java | 5 ++- .../repository/dao/MongoJobInstanceDao.java | 20 +++++------- 5 files changed, 26 insertions(+), 40 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java index f10a5fa30e..0b839c7d80 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java @@ -76,7 +76,10 @@ public interface JobExplorer { * @param start The start index of the instances to return. * @param count The maximum number of instances to return. * @return a list of {@link JobInstance} for the requested job name. + * @deprecated Since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} */ + @Deprecated(forRemoval = true) List findJobInstancesByJobName(String jobName, int start, int count); /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java index 236be9902d..58b86d037a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java @@ -230,9 +230,14 @@ private void getStepExecutionDependencies(StepExecution stepExecution) { } } + /** + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} instead. + */ + @Deprecated(forRemoval = true) @Override public List findJobInstancesByJobName(String jobName, int start, int count) { - return jobInstanceDao.findJobInstancesByName(jobName, start, count); + return getJobInstances(jobName, start, count); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java index 8b503899a9..b7e94badbd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java @@ -332,33 +332,14 @@ public JobInstance mapRow(ResultSet rs, int rowNum) throws SQLException { } + /** + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} instead. + */ + @Deprecated(forRemoval = true) @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) public List findJobInstancesByName(String jobName, final int start, final int count) { - ResultSetExtractor extractor = new ResultSetExtractor() { - private final List list = new ArrayList<>(); - - @Override - public Object extractData(ResultSet rs) throws SQLException, DataAccessException { - int rowNum = 0; - while (rowNum < start && rs.next()) { - rowNum++; - } - while (rowNum < start + count && rs.next()) { - RowMapper rowMapper = new JobInstanceRowMapper(); - list.add(rowMapper.mapRow(rs, rowNum)); - rowNum++; - } - return list; - } - }; - - if (jobName.contains(STAR_WILDCARD)) { - jobName = jobName.replaceAll("\\" + STAR_WILDCARD, SQL_WILDCARD); - } - - return (List) getJdbcTemplate().query(getQuery(FIND_LAST_JOBS_LIKE_NAME), extractor, jobName); - + return getJobInstances(jobName, start, count); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java index 4c2ac43be4..c430043ed1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -117,7 +117,10 @@ default JobInstance getLastJobInstance(String jobName) { * should begin. * @param count int containing the number of job instances to return. * @return a list of {@link JobInstance} for the job name requested. + * @deprecated Since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} */ + @Deprecated(forRemoval = true) List findJobInstancesByName(String jobName, int start, int count); /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MongoJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MongoJobInstanceDao.java index b967e35f77..a325b34bde 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MongoJobInstanceDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MongoJobInstanceDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 the original author or authors. + * Copyright 2024-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -143,20 +143,14 @@ public List getJobNames() { .toList(); } + /** + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} instead. + */ + @Deprecated(forRemoval = true) @Override public List findJobInstancesByName(String jobName, int start, int count) { - Query query = query(where("jobName").alike(Example.of(jobName))); - Sort.Order sortOrder = Sort.Order.desc("jobInstanceId"); - List jobInstances = this.mongoOperations - .find(query.with(Sort.by(sortOrder)), - org.springframework.batch.core.repository.persistence.JobInstance.class, COLLECTION_NAME) - .stream() - .toList(); - return jobInstances.subList(start, jobInstances.size()) - .stream() - .map(this.jobInstanceConverter::toJobInstance) - .limit(count) - .toList(); + return getJobInstances(jobName, start, count); } @Override From b8c93d677ed86130262042fb8565ce30816c2270 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Mon, 5 May 2025 15:26:43 +0200 Subject: [PATCH 007/182] Make JobRepository extend JobExplorer Resolves #4824 --- .../batch/core/explore/JobExplorer.java | 126 +++++++++-- .../explore/support/SimpleJobExplorer.java | 209 ++++++++++++------ .../batch/core/repository/JobRepository.java | 98 +------- .../support/SimpleJobRepository.java | 98 +------- 4 files changed, 264 insertions(+), 267 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java index 0b839c7d80..6ee09295e9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java @@ -15,6 +15,7 @@ */ package org.springframework.batch.core.explore; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -51,7 +52,9 @@ public interface JobExplorer { * alphabetically). * @return the list of job names that have been executed. */ - List getJobNames(); + default List getJobNames() { + return Collections.emptyList(); + } /* * =================================================================================== @@ -67,7 +70,9 @@ public interface JobExplorer { * @param count The maximum number of instances to return. * @return the {@link JobInstance} values up to a maximum of count values. */ - List getJobInstances(String jobName, int start, int count); + default List getJobInstances(String jobName, int start, int count) { + return Collections.emptyList(); + } /** * Fetch {@link JobInstance} values in descending order of creation (and, therefore, @@ -79,8 +84,51 @@ public interface JobExplorer { * @deprecated Since v6.0 and scheduled for removal in v6.2. Use * {@link #getJobInstances(String, int, int)} */ - @Deprecated(forRemoval = true) - List findJobInstancesByJobName(String jobName, int start, int count); + @Deprecated(since = "6.0", forRemoval = true) + default List findJobInstancesByJobName(String jobName, int start, int count) { + return Collections.emptyList(); + } + + /** + * Fetch the last job instances with the provided name, sorted backwards by primary + * key, using a 'like' criteria + * @param jobName {@link String} containing the name of the job. + * @param start int containing the offset of where list of job instances results + * should begin. + * @param count int containing the number of job instances to return. + * @return a list of {@link JobInstance} for the job name requested. + * @since 5.0 + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} + */ + @Deprecated(since = "6.0", forRemoval = true) + default List findJobInstancesByName(String jobName, int start, int count) { + return Collections.emptyList(); + } + + /** + * Check if an instance of this job already exists with the parameters provided. + * @param jobName the name of the job + * @param jobParameters the parameters to match + * @return true if a {@link JobInstance} already exists for this job name and job + * parameters + * @deprecated Since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstance(String, JobParameters)} and check for {@code null} result + * instead. + */ + @Deprecated(since = "6.0", forRemoval = true) + default boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { + return getJobInstance(jobName, jobParameters) != null; + } + + /** + * @param instanceId {@link Long} The ID for the {@link JobInstance} to obtain. + * @return the {@code JobInstance} that has this ID, or {@code null} if not found. + */ + @Nullable + default JobInstance getJobInstance(@Nullable Long instanceId) { + throw new UnsupportedOperationException(); + } /** * Find the last job instance, by ID, for the given job. @@ -94,13 +142,6 @@ default JobInstance getLastJobInstance(String jobName) { throw new UnsupportedOperationException(); } - /** - * @param instanceId {@link Long} The ID for the {@link JobInstance} to obtain. - * @return the {@code JobInstance} that has this ID, or {@code null} if not found. - */ - @Nullable - JobInstance getJobInstance(@Nullable Long instanceId); - /** * @param jobName {@link String} name of the job. * @param jobParameters {@link JobParameters} parameters for the job instance. @@ -123,7 +164,9 @@ default JobInstance getJobInstance(String jobName, JobParameters jobParameters) * @throws NoSuchJobException thrown when there is no {@link JobInstance} for the * jobName specified. */ - long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException; + default long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException { + throw new UnsupportedOperationException(); + } /* * =================================================================================== @@ -140,7 +183,9 @@ default JobInstance getJobInstance(String jobName, JobParameters jobParameters) * @return the {@link JobExecution} that has this ID or {@code null} if not found. */ @Nullable - JobExecution getJobExecution(@Nullable Long executionId); + default JobExecution getJobExecution(@Nullable Long executionId) { + throw new UnsupportedOperationException(); + } /** * Retrieve job executions by their job instance. The corresponding step executions @@ -150,7 +195,23 @@ default JobInstance getJobInstance(String jobName, JobParameters jobParameters) * @param jobInstance The {@link JobInstance} to query. * @return the list of all executions for the specified {@link JobInstance}. */ - List getJobExecutions(JobInstance jobInstance); + default List getJobExecutions(JobInstance jobInstance) { + return Collections.emptyList(); + } + + /** + * Return all {@link JobExecution}s for given {@link JobInstance}, sorted backwards by + * creation order (so the first element is the most recent). + * @param jobInstance parent {@link JobInstance} of the {@link JobExecution}s to find. + * @return {@link List} containing JobExecutions for the jobInstance. + * @since 5.0 + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobExecutions(JobInstance)} + */ + @Deprecated(since = "6.0", forRemoval = true) + default List findJobExecutions(JobInstance jobInstance) { + return Collections.emptyList(); + } /** * Find the last {@link JobExecution} that has been created for a given @@ -167,6 +228,16 @@ default JobExecution getLastJobExecution(JobInstance jobInstance) { throw new UnsupportedOperationException(); } + /** + * @param jobName the name of the job that might have run + * @param jobParameters parameters identifying the {@link JobInstance} + * @return the last execution of job if exists, null otherwise + */ + @Nullable + default JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { + throw new UnsupportedOperationException(); + } + /** * Retrieve running job executions. The corresponding step executions may not be fully * hydrated (for example, their execution context may be missing), depending on the @@ -175,7 +246,9 @@ default JobExecution getLastJobExecution(JobInstance jobInstance) { * @param jobName The name of the job. * @return the set of running executions for jobs with the specified name. */ - Set findRunningJobExecutions(@Nullable String jobName); + default Set findRunningJobExecutions(@Nullable String jobName) { + return Collections.emptySet(); + } /* * =================================================================================== @@ -195,6 +268,27 @@ default JobExecution getLastJobExecution(JobInstance jobInstance) { * @see #getJobExecution(Long) */ @Nullable - StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable Long stepExecutionId); + default StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable Long stepExecutionId) { + throw new UnsupportedOperationException(); + } + + /** + * @param jobInstance {@link JobInstance} instance containing the step executions. + * @param stepName the name of the step execution that might have run. + * @return the last execution of step for the given job instance. + */ + @Nullable + default StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { + throw new UnsupportedOperationException(); + } + + /** + * @param jobInstance {@link JobInstance} instance containing the step executions. + * @param stepName the name of the step execution that might have run. + * @return the execution count of the step within the given job instance. + */ + default long getStepExecutionCount(JobInstance jobInstance, String stepName) { + throw new UnsupportedOperationException(); + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java index 58b86d037a..bf8857b16a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.springframework.batch.core.repository.dao.JobExecutionDao; import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.core.repository.dao.StepExecutionDao; +import org.springframework.batch.item.ExecutionContext; import org.springframework.lang.Nullable; import java.util.List; @@ -49,20 +50,13 @@ */ public class SimpleJobExplorer implements JobExplorer { - private JobInstanceDao jobInstanceDao; + protected JobInstanceDao jobInstanceDao; - private JobExecutionDao jobExecutionDao; + protected JobExecutionDao jobExecutionDao; - private StepExecutionDao stepExecutionDao; + protected StepExecutionDao stepExecutionDao; - private ExecutionContextDao ecDao; - - /** - * Provides a default constructor with low visibility in case you want to use - * aop:proxy-target-class="true" for the AOP interceptor. - */ - SimpleJobExplorer() { - } + protected ExecutionContextDao ecDao; /** * Constructor to initialize the job {@link SimpleJobExplorer}. @@ -80,6 +74,79 @@ public SimpleJobExplorer(JobInstanceDao jobInstanceDao, JobExecutionDao jobExecu this.ecDao = ecDao; } + /* + * =================================================================================== + * Job operations + * =================================================================================== + */ + + @Override + public List getJobNames() { + return jobInstanceDao.getJobNames(); + } + + /* + * =================================================================================== + * Job instance operations + * =================================================================================== + */ + + @Override + @Deprecated(since = "6.0", forRemoval = true) + public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { + return jobInstanceDao.getJobInstance(jobName, jobParameters) != null; + } + + /** + * @deprecated since v6.0 and scheduled for removal in v6.2. Use + * {@link #getJobInstances(String, int, int)} instead. + */ + @Deprecated(since = "6.0", forRemoval = true) + @Override + public List findJobInstancesByJobName(String jobName, int start, int count) { + return getJobInstances(jobName, start, count); + } + + @Override + @Deprecated(since = "6.0", forRemoval = true) + public List findJobInstancesByName(String jobName, int start, int count) { + return this.jobInstanceDao.findJobInstancesByName(jobName, start, count); + } + + @Nullable + @Override + public JobInstance getJobInstance(@Nullable Long instanceId) { + return jobInstanceDao.getJobInstance(instanceId); + } + + @Nullable + @Override + public JobInstance getJobInstance(String jobName, JobParameters jobParameters) { + return jobInstanceDao.getJobInstance(jobName, jobParameters); + } + + @Nullable + @Override + public JobInstance getLastJobInstance(String jobName) { + return jobInstanceDao.getLastJobInstance(jobName); + } + + @Override + public List getJobInstances(String jobName, int start, int count) { + return jobInstanceDao.getJobInstances(jobName, start, count); + } + + @Override + public long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException { + return jobInstanceDao.getJobInstanceCount(jobName); + } + + /* + * =================================================================================== + * Job execution operations + * =================================================================================== + */ + @Override public List getJobExecutions(JobInstance jobInstance) { List executions = jobExecutionDao.findJobExecutions(jobInstance); @@ -105,6 +172,32 @@ public JobExecution getLastJobExecution(JobInstance jobInstance) { return lastJobExecution; } + @Deprecated(since = "6.0", forRemoval = true) + @Override + public List findJobExecutions(JobInstance jobInstance) { + List jobExecutions = this.jobExecutionDao.findJobExecutions(jobInstance); + for (JobExecution jobExecution : jobExecutions) { + this.stepExecutionDao.addStepExecutions(jobExecution); + } + return jobExecutions; + } + + @Override + @Nullable + public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { + JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters); + if (jobInstance == null) { + return null; + } + JobExecution jobExecution = jobExecutionDao.getLastJobExecution(jobInstance); + + if (jobExecution != null) { + jobExecution.setExecutionContext(ecDao.getExecutionContext(jobExecution)); + stepExecutionDao.addStepExecutions(jobExecution); + } + return jobExecution; + } + @Override public Set findRunningJobExecutions(@Nullable String jobName) { Set executions = jobExecutionDao.findRunningJobExecutions(jobName); @@ -134,6 +227,24 @@ public JobExecution getJobExecution(@Nullable Long executionId) { return jobExecution; } + /* + * Find all dependencies for a JobExecution, including JobInstance (which requires + * JobParameters) plus StepExecutions + */ + private void getJobExecutionDependencies(JobExecution jobExecution) { + JobInstance jobInstance = jobInstanceDao.getJobInstance(jobExecution); + stepExecutionDao.addStepExecutions(jobExecution); + jobExecution.setJobInstance(jobInstance); + jobExecution.setExecutionContext(ecDao.getExecutionContext(jobExecution)); + + } + + /* + * =================================================================================== + * Step execution operations + * =================================================================================== + */ + @Nullable @Override public StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable Long executionId) { @@ -147,39 +258,41 @@ public StepExecution getStepExecution(@Nullable Long jobExecutionId, @Nullable L return stepExecution; } - @Nullable @Override - public JobInstance getJobInstance(@Nullable Long instanceId) { - return jobInstanceDao.getJobInstance(instanceId); - } - @Nullable - @Override - public JobInstance getJobInstance(String jobName, JobParameters jobParameters) { - return jobInstanceDao.getJobInstance(jobName, jobParameters); - } + public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { + StepExecution latest = stepExecutionDao.getLastStepExecution(jobInstance, stepName); - @Nullable - @Override - public JobInstance getLastJobInstance(String jobName) { - return jobInstanceDao.getLastJobInstance(jobName); - } + if (latest != null) { + ExecutionContext stepExecutionContext = ecDao.getExecutionContext(latest); + latest.setExecutionContext(stepExecutionContext); + ExecutionContext jobExecutionContext = ecDao.getExecutionContext(latest.getJobExecution()); + latest.getJobExecution().setExecutionContext(jobExecutionContext); + } - @Override - public List getJobInstances(String jobName, int start, int count) { - return jobInstanceDao.getJobInstances(jobName, start, count); + return latest; } + /** + * @return number of executions of the step within given job instance + */ @Override - public List getJobNames() { - return jobInstanceDao.getJobNames(); + public long getStepExecutionCount(JobInstance jobInstance, String stepName) { + return stepExecutionDao.countStepExecutions(jobInstance, stepName); } - @Override - public long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException { - return jobInstanceDao.getJobInstanceCount(jobName); + private void getStepExecutionDependencies(StepExecution stepExecution) { + if (stepExecution != null) { + stepExecution.setExecutionContext(ecDao.getExecutionContext(stepExecution)); + } } + /* + * =================================================================================== + * protected methods + * =================================================================================== + */ + /** * @return instance of {@link JobInstanceDao}. * @since 5.1 @@ -212,32 +325,4 @@ protected ExecutionContextDao getEcDao() { return ecDao; } - /* - * Find all dependencies for a JobExecution, including JobInstance (which requires - * JobParameters) plus StepExecutions - */ - private void getJobExecutionDependencies(JobExecution jobExecution) { - JobInstance jobInstance = jobInstanceDao.getJobInstance(jobExecution); - stepExecutionDao.addStepExecutions(jobExecution); - jobExecution.setJobInstance(jobInstance); - jobExecution.setExecutionContext(ecDao.getExecutionContext(jobExecution)); - - } - - private void getStepExecutionDependencies(StepExecution stepExecution) { - if (stepExecution != null) { - stepExecution.setExecutionContext(ecDao.getExecutionContext(stepExecution)); - } - } - - /** - * @deprecated since v6.0 and scheduled for removal in v6.2. Use - * {@link #getJobInstances(String, int, int)} instead. - */ - @Deprecated(forRemoval = true) - @Override - public List findJobInstancesByJobName(String jobName, int start, int count) { - return getJobInstances(jobName, start, count); - } - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java index b4c7d3da88..5fdc6be7bd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java @@ -22,15 +22,13 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.repository.dao.JobExecutionDao; import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.item.ExecutionContext; -import org.springframework.lang.Nullable; import org.springframework.transaction.annotation.Isolation; import java.util.Collection; -import java.util.Collections; -import java.util.List; /** *

    @@ -48,99 +46,7 @@ * @author Mahmoud Ben Hassine * @author Parikshit Dutta */ -public interface JobRepository { - - /* - * =================================================================================== - * Read only operations - * =================================================================================== - */ - - /** - * Retrieve the names of all job instances sorted alphabetically - i.e. jobs that have - * ever been executed. - * @return the names of all job instances - * @since 5.0 - */ - default List getJobNames() { - return Collections.emptyList(); - } - - /** - * Fetch the last job instances with the provided name, sorted backwards by primary - * key, using a 'like' criteria - * @param jobName {@link String} containing the name of the job. - * @param start int containing the offset of where list of job instances results - * should begin. - * @param count int containing the number of job instances to return. - * @return a list of {@link JobInstance} for the job name requested. - * @since 5.0 - */ - default List findJobInstancesByName(String jobName, int start, int count) { - return Collections.emptyList(); - } - - /** - * Check if an instance of this job already exists with the parameters provided. - * @param jobName the name of the job - * @param jobParameters the parameters to match - * @return true if a {@link JobInstance} already exists for this job name and job - * parameters - */ - boolean isJobInstanceExists(String jobName, JobParameters jobParameters); - - /** - * @param jobName {@link String} name of the job. - * @param jobParameters {@link JobParameters} parameters for the job instance. - * @return the {@link JobInstance} with the given name and parameters, or - * {@code null}. - * - * @since 5.0 - */ - @Nullable - default JobInstance getJobInstance(String jobName, JobParameters jobParameters) { - throw new UnsupportedOperationException(); - } - - /** - * Return all {@link JobExecution}s for given {@link JobInstance}, sorted backwards by - * creation order (so the first element is the most recent). - * @param jobInstance parent {@link JobInstance} of the {@link JobExecution}s to find. - * @return {@link List} containing JobExecutions for the jobInstance. - * @since 5.0 - */ - default List findJobExecutions(JobInstance jobInstance) { - return Collections.emptyList(); - } - - /** - * @param jobName the name of the job that might have run - * @param jobParameters parameters identifying the {@link JobInstance} - * @return the last execution of job if exists, null otherwise - */ - @Nullable - JobExecution getLastJobExecution(String jobName, JobParameters jobParameters); - - /** - * @param jobInstance {@link JobInstance} instance containing the step executions. - * @param stepName the name of the step execution that might have run. - * @return the last execution of step for the given job instance. - */ - @Nullable - StepExecution getLastStepExecution(JobInstance jobInstance, String stepName); - - /** - * @param jobInstance {@link JobInstance} instance containing the step executions. - * @param stepName the name of the step execution that might have run. - * @return the execution count of the step within the given job instance. - */ - long getStepExecutionCount(JobInstance jobInstance, String stepName); - - /* - * =================================================================================== - * Write/Update operations - * =================================================================================== - */ +public interface JobRepository extends JobExplorer { /** * Create a new {@link JobInstance} with the name and job parameters provided. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java index e98752c987..60c906b093 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 the original author or authors. + * Copyright 2006-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import org.springframework.batch.core.JobInstance; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.support.SimpleJobExplorer; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; import org.springframework.batch.core.repository.JobRepository; @@ -32,7 +33,6 @@ import org.springframework.batch.core.repository.dao.JobInstanceDao; import org.springframework.batch.core.repository.dao.StepExecutionDao; import org.springframework.batch.item.ExecutionContext; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import java.time.LocalDateTime; @@ -60,56 +60,13 @@ * @see StepExecutionDao * */ -public class SimpleJobRepository implements JobRepository { +public class SimpleJobRepository extends SimpleJobExplorer implements JobRepository { private static final Log logger = LogFactory.getLog(SimpleJobRepository.class); - private JobInstanceDao jobInstanceDao; - - private JobExecutionDao jobExecutionDao; - - private StepExecutionDao stepExecutionDao; - - private ExecutionContextDao ecDao; - - /** - * Provide default constructor with low visibility in case user wants to use - * aop:proxy-target-class="true" for AOP interceptor. - */ - SimpleJobRepository() { - } - public SimpleJobRepository(JobInstanceDao jobInstanceDao, JobExecutionDao jobExecutionDao, StepExecutionDao stepExecutionDao, ExecutionContextDao ecDao) { - super(); - this.jobInstanceDao = jobInstanceDao; - this.jobExecutionDao = jobExecutionDao; - this.stepExecutionDao = stepExecutionDao; - this.ecDao = ecDao; - } - - @Override - public List getJobNames() { - return this.jobInstanceDao.getJobNames(); - } - - @Override - public List findJobInstancesByName(String jobName, int start, int count) { - return this.jobInstanceDao.findJobInstancesByName(jobName, start, count); - } - - @Override - public List findJobExecutions(JobInstance jobInstance) { - List jobExecutions = this.jobExecutionDao.findJobExecutions(jobInstance); - for (JobExecution jobExecution : jobExecutions) { - this.stepExecutionDao.addStepExecutions(jobExecution); - } - return jobExecutions; - } - - @Override - public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { - return jobInstanceDao.getJobInstance(jobName, jobParameters) != null; + super(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao); } @Override @@ -249,34 +206,6 @@ public void updateExecutionContext(JobExecution jobExecution) { ecDao.updateExecutionContext(jobExecution); } - @Override - public JobInstance getJobInstance(String jobName, JobParameters jobParameters) { - return jobInstanceDao.getJobInstance(jobName, jobParameters); - } - - @Override - @Nullable - public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { - StepExecution latest = stepExecutionDao.getLastStepExecution(jobInstance, stepName); - - if (latest != null) { - ExecutionContext stepExecutionContext = ecDao.getExecutionContext(latest); - latest.setExecutionContext(stepExecutionContext); - ExecutionContext jobExecutionContext = ecDao.getExecutionContext(latest.getJobExecution()); - latest.getJobExecution().setExecutionContext(jobExecutionContext); - } - - return latest; - } - - /** - * @return number of executions of the step within given job instance - */ - @Override - public long getStepExecutionCount(JobInstance jobInstance, String stepName) { - return stepExecutionDao.countStepExecutions(jobInstance, stepName); - } - /** * Check to determine whether or not the JobExecution that is the parent of the * provided StepExecution has been interrupted. If, after synchronizing the status @@ -293,23 +222,6 @@ private void checkForInterruption(StepExecution stepExecution) { } } - @Override - @Nullable - public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { - JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters); - if (jobInstance == null) { - return null; - } - JobExecution jobExecution = jobExecutionDao.getLastJobExecution(jobInstance); - - if (jobExecution != null) { - jobExecution.setExecutionContext(ecDao.getExecutionContext(jobExecution)); - stepExecutionDao.addStepExecutions(jobExecution); - } - return jobExecution; - - } - @Override public void deleteStepExecution(StepExecution stepExecution) { this.ecDao.deleteExecutionContext(stepExecution); @@ -328,7 +240,7 @@ public void deleteJobExecution(JobExecution jobExecution) { @Override public void deleteJobInstance(JobInstance jobInstance) { - List jobExecutions = findJobExecutions(jobInstance); + List jobExecutions = getJobExecutions(jobInstance); for (JobExecution jobExecution : jobExecutions) { deleteJobExecution(jobExecution); } From 6992b79b8dc6f6e87f1dd75548328f9011ec699e Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Mon, 5 May 2025 17:14:12 +0200 Subject: [PATCH 008/182] Remove dependency to JobExplorer in SimpleJobOperator Resolves #4817 --- .../annotation/BatchRegistrar.java | 1 - .../support/DefaultBatchConfiguration.java | 6 +- .../support/JobOperatorFactoryBean.java | 12 ---- .../launch/support/SimpleJobOperator.java | 25 ++----- .../support/JobOperatorFactoryBeanTests.java | 2 - .../support/SimpleJobOperatorTests.java | 66 +++++++++---------- .../OptimisticLockingFailureTests-context.xml | 1 - .../resources/simple-job-launcher-context.xml | 3 +- .../misc/jmx/adhoc-job-launcher-context.xml | 5 -- .../job/skipSample-job-launcher-context.xml | 2 +- .../resources/simple-job-launcher-context.xml | 3 +- 11 files changed, 42 insertions(+), 84 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java index 073ef836d9..631f12b262 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java @@ -254,7 +254,6 @@ private void registerJobOperator(BeanDefinitionRegistry registry, EnableBatchPro beanDefinitionBuilder.addPropertyReference(JOB_REPOSITORY, JOB_REPOSITORY); beanDefinitionBuilder.addPropertyReference(JOB_LAUNCHER, JOB_LAUNCHER); - beanDefinitionBuilder.addPropertyReference(JOB_EXPLORER, JOB_EXPLORER); beanDefinitionBuilder.addPropertyReference(JOB_REGISTRY, JOB_REGISTRY); // set optional properties diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java index 484809fb2e..1a628b3d93 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java @@ -197,7 +197,6 @@ public JobRegistry jobRegistry() throws BatchConfigurationException { /** * Define a job operator bean. * @param jobRepository a job repository - * @param jobExplorer a job explorer * @param jobRegistry a job registry * @param jobLauncher a job launcher * @return a job operator @@ -205,12 +204,11 @@ public JobRegistry jobRegistry() throws BatchConfigurationException { * @since 5.2 */ @Bean - public JobOperator jobOperator(JobRepository jobRepository, JobExplorer jobExplorer, JobRegistry jobRegistry, - JobLauncher jobLauncher) throws BatchConfigurationException { + public JobOperator jobOperator(JobRepository jobRepository, JobRegistry jobRegistry, JobLauncher jobLauncher) + throws BatchConfigurationException { JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean(); jobOperatorFactoryBean.setTransactionManager(getTransactionManager()); jobOperatorFactoryBean.setJobRepository(jobRepository); - jobOperatorFactoryBean.setJobExplorer(jobExplorer); jobOperatorFactoryBean.setJobRegistry(jobRegistry); jobOperatorFactoryBean.setJobLauncher(jobLauncher); jobOperatorFactoryBean.setJobParametersConverter(getJobParametersConverter()); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java index a3c07375ec..fdeea5a3a0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java @@ -61,8 +61,6 @@ public class JobOperatorFactoryBean implements FactoryBean, Initial private JobRepository jobRepository; - private JobExplorer jobExplorer; - private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter(); private final ProxyFactory proxyFactory = new ProxyFactory(); @@ -72,7 +70,6 @@ public void afterPropertiesSet() throws Exception { Assert.notNull(this.transactionManager, "TransactionManager must not be null"); Assert.notNull(this.jobLauncher, "JobLauncher must not be null"); Assert.notNull(this.jobRegistry, "JobRegistry must not be null"); - Assert.notNull(this.jobExplorer, "JobExplorer must not be null"); Assert.notNull(this.jobRepository, "JobRepository must not be null"); if (this.transactionAttributeSource == null) { Properties transactionAttributes = new Properties(); @@ -108,14 +105,6 @@ public void setJobRepository(JobRepository jobRepository) { this.jobRepository = jobRepository; } - /** - * Setter for the job explorer. - * @param jobExplorer the job explorer to set - */ - public void setJobExplorer(JobExplorer jobExplorer) { - this.jobExplorer = jobExplorer; - } - /** * Setter for the job parameters converter. * @param jobParametersConverter the job parameters converter to set @@ -166,7 +155,6 @@ public JobOperator getObject() throws Exception { private SimpleJobOperator getTarget() throws Exception { SimpleJobOperator simpleJobOperator = new SimpleJobOperator(); simpleJobOperator.setJobRegistry(this.jobRegistry); - simpleJobOperator.setJobExplorer(this.jobExplorer); simpleJobOperator.setJobRepository(this.jobRepository); simpleJobOperator.setJobLauncher(this.jobLauncher); simpleJobOperator.setJobParametersConverter(this.jobParametersConverter); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java index 059e769960..5c28562b78 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java @@ -93,8 +93,6 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { private ListableJobLocator jobRegistry; - private JobExplorer jobExplorer; - private JobLauncher jobLauncher; private JobRepository jobRepository; @@ -112,7 +110,6 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { public void afterPropertiesSet() throws Exception { Assert.state(jobLauncher != null, "JobLauncher must be provided"); Assert.state(jobRegistry != null, "JobLocator must be provided"); - Assert.state(jobExplorer != null, "JobExplorer must be provided"); Assert.state(jobRepository != null, "JobRepository must be provided"); } @@ -132,14 +129,6 @@ public void setJobRegistry(ListableJobLocator jobRegistry) { this.jobRegistry = jobRegistry; } - /** - * Public setter for the {@link JobExplorer}. - * @param jobExplorer the {@link JobExplorer} to set - */ - public void setJobExplorer(JobExplorer jobExplorer) { - this.jobExplorer = jobExplorer; - } - public void setJobRepository(JobRepository jobRepository) { this.jobRepository = jobRepository; } @@ -154,12 +143,12 @@ public void setJobLauncher(JobLauncher jobLauncher) { @Override public List getExecutions(long instanceId) throws NoSuchJobInstanceException { - JobInstance jobInstance = jobExplorer.getJobInstance(instanceId); + JobInstance jobInstance = jobRepository.getJobInstance(instanceId); if (jobInstance == null) { throw new NoSuchJobInstanceException(String.format("No job instance with id=%d", instanceId)); } List list = new ArrayList<>(); - for (JobExecution jobExecution : jobExplorer.getJobExecutions(jobInstance)) { + for (JobExecution jobExecution : jobRepository.getJobExecutions(jobInstance)) { list.add(jobExecution.getId()); } return list; @@ -173,7 +162,7 @@ public Set getJobNames() { @Override public List getJobInstances(String jobName, int start, int count) throws NoSuchJobException { List list = new ArrayList<>(); - List jobInstances = jobExplorer.getJobInstances(jobName, start, count); + List jobInstances = jobRepository.getJobInstances(jobName, start, count); for (JobInstance jobInstance : jobInstances) { list.add(jobInstance.getId()); } @@ -186,7 +175,7 @@ public List getJobInstances(String jobName, int start, int count) throws N @Override @Nullable public JobInstance getJobInstance(String jobName, JobParameters jobParameters) { - return this.jobExplorer.getJobInstance(jobName, jobParameters); + return this.jobRepository.getJobInstance(jobName, jobParameters); } @Override @@ -201,7 +190,7 @@ public String getParameters(long executionId) throws NoSuchJobExecutionException @Override public Set getRunningExecutions(String jobName) throws NoSuchJobException { Set set = new LinkedHashSet<>(); - for (JobExecution jobExecution : jobExplorer.findRunningJobExecutions(jobName)) { + for (JobExecution jobExecution : jobRepository.findRunningJobExecutions(jobName)) { set.add(jobExecution.getId()); } if (set.isEmpty() && !jobRegistry.getJobNames().contains(jobName)) { @@ -299,7 +288,7 @@ public Long startNextInstance(String jobName) } Job job = jobRegistry.getJob(jobName); - JobParameters parameters = new JobParametersBuilder(jobExplorer).getNextJobParameters(job).toJobParameters(); + JobParameters parameters = new JobParametersBuilder(jobRepository).getNextJobParameters(job).toJobParameters(); if (logger.isInfoEnabled()) { logger.info(String.format("Attempting to launch job with name=%s and parameters=%s", jobName, parameters)); } @@ -389,7 +378,7 @@ public JobExecution abandon(long jobExecutionId) } private JobExecution findExecutionById(long executionId) throws NoSuchJobExecutionException { - JobExecution jobExecution = jobExplorer.getJobExecution(executionId); + JobExecution jobExecution = jobRepository.getJobExecution(executionId); if (jobExecution == null) { throw new NoSuchJobExecutionException("No JobExecution found for id: [" + executionId + "]"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java index c09cbe5925..e8c8778a90 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java @@ -57,7 +57,6 @@ public void testJobOperatorCreation() throws Exception { JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean(); jobOperatorFactoryBean.setTransactionManager(this.transactionManager); jobOperatorFactoryBean.setJobLauncher(this.jobLauncher); - jobOperatorFactoryBean.setJobExplorer(this.jobExplorer); jobOperatorFactoryBean.setJobRegistry(this.jobRegistry); jobOperatorFactoryBean.setJobRepository(this.jobRepository); jobOperatorFactoryBean.setJobParametersConverter(this.jobParametersConverter); @@ -80,7 +79,6 @@ public void testCustomTransactionAttributesSource() throws Exception { JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean(); jobOperatorFactoryBean.setTransactionManager(this.transactionManager); jobOperatorFactoryBean.setJobLauncher(this.jobLauncher); - jobOperatorFactoryBean.setJobExplorer(this.jobExplorer); jobOperatorFactoryBean.setJobRegistry(this.jobRegistry); jobOperatorFactoryBean.setJobRepository(this.jobRepository); jobOperatorFactoryBean.setJobParametersConverter(this.jobParametersConverter); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java index d5d3951c2c..412e7d9787 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java @@ -79,8 +79,6 @@ class SimpleJobOperatorTests { protected Job job; - private JobExplorer jobExplorer; - private JobRepository jobRepository; private JobParameters jobParameters; @@ -120,10 +118,6 @@ public Set getJobNames() { jobOperator.setJobLauncher( (job, jobParameters) -> new JobExecution(new JobInstance(123L, job.getName()), 999L, jobParameters)); - jobExplorer = mock(); - - jobOperator.setJobExplorer(jobExplorer); - jobRepository = mock(); jobOperator.setJobRepository(jobRepository); @@ -159,8 +153,8 @@ void testMandatoryProperties() { void testStartNextInstanceSunnyDay() throws Exception { jobParameters = new JobParameters(); JobInstance jobInstance = new JobInstance(321L, "foo"); - when(jobExplorer.getJobInstances("foo", 0, 1)).thenReturn(Collections.singletonList(jobInstance)); - when(jobExplorer.getJobExecutions(jobInstance)) + when(jobRepository.getJobInstances("foo", 0, 1)).thenReturn(Collections.singletonList(jobInstance)); + when(jobRepository.getJobExecutions(jobInstance)) .thenReturn(Collections.singletonList(new JobExecution(jobInstance, new JobParameters()))); Long value = jobOperator.startNextInstance("foo"); assertEquals(999, value.longValue()); @@ -190,9 +184,9 @@ void testStartNewInstanceAlreadyExists() { @Test void testResumeSunnyDay() throws Exception { jobParameters = new JobParameters(); - when(jobExplorer.getJobExecution(111L)) + when(jobRepository.getJobExecution(111L)) .thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); Long value = jobOperator.restart(111L); assertEquals(999, value.longValue()); } @@ -201,8 +195,8 @@ void testResumeSunnyDay() throws Exception { void testGetSummarySunnyDay() throws Exception { jobParameters = new JobParameters(); JobExecution jobExecution = new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); - jobExplorer.getJobExecution(111L); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); + jobRepository.getJobExecution(111L); String value = jobOperator.getSummary(111L); assertEquals(jobExecution.toString(), value); } @@ -210,7 +204,7 @@ void testGetSummarySunnyDay() throws Exception { @Test void testGetSummaryNoSuchExecution() { jobParameters = new JobParameters(); - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); assertThrows(NoSuchJobExecutionException.class, () -> jobOperator.getSummary(111L)); } @@ -222,7 +216,7 @@ void testGetStepExecutionSummariesSunnyDay() throws Exception { jobExecution.createStepExecution("step1"); jobExecution.createStepExecution("step2"); jobExecution.getStepExecutions().iterator().next().setId(21L); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); Map value = jobOperator.getStepExecutionSummaries(111L); assertEquals(2, value.size()); } @@ -230,7 +224,7 @@ void testGetStepExecutionSummariesSunnyDay() throws Exception { @Test void testGetStepExecutionSummariesNoSuchExecution() { jobParameters = new JobParameters(); - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); assertThrows(NoSuchJobExecutionException.class, () -> jobOperator.getStepExecutionSummaries(111L)); } @@ -238,7 +232,7 @@ void testGetStepExecutionSummariesNoSuchExecution() { void testFindRunningExecutionsSunnyDay() throws Exception { jobParameters = new JobParameters(); JobExecution jobExecution = new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters); - when(jobExplorer.findRunningJobExecutions("foo")).thenReturn(Collections.singleton(jobExecution)); + when(jobRepository.findRunningJobExecutions("foo")).thenReturn(Collections.singleton(jobExecution)); Set value = jobOperator.getRunningExecutions("foo"); assertEquals(111L, value.iterator().next().longValue()); } @@ -247,14 +241,14 @@ void testFindRunningExecutionsSunnyDay() throws Exception { @SuppressWarnings("unchecked") void testFindRunningExecutionsNoSuchJob() { jobParameters = new JobParameters(); - when(jobExplorer.findRunningJobExecutions("no-such-job")).thenReturn(Collections.EMPTY_SET); + when(jobRepository.findRunningJobExecutions("no-such-job")).thenReturn(Collections.EMPTY_SET); assertThrows(NoSuchJobException.class, () -> jobOperator.getRunningExecutions("no-such-job")); } @Test void testGetJobParametersSunnyDay() throws Exception { final JobParameters jobParameters = new JobParameters(); - when(jobExplorer.getJobExecution(111L)) + when(jobRepository.getJobExecution(111L)) .thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); String value = jobOperator.getParameters(111L); assertEquals("a=b", value); @@ -262,7 +256,7 @@ void testGetJobParametersSunnyDay() throws Exception { @Test void testGetJobParametersNoSuchExecution() { - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); assertThrows(NoSuchJobExecutionException.class, () -> jobOperator.getParameters(111L)); } @@ -270,8 +264,8 @@ void testGetJobParametersNoSuchExecution() { void testGetLastInstancesSunnyDay() throws Exception { jobParameters = new JobParameters(); JobInstance jobInstance = new JobInstance(123L, job.getName()); - when(jobExplorer.getJobInstances("foo", 0, 2)).thenReturn(Collections.singletonList(jobInstance)); - jobExplorer.getJobInstances("foo", 0, 2); + when(jobRepository.getJobInstances("foo", 0, 2)).thenReturn(Collections.singletonList(jobInstance)); + jobRepository.getJobInstances("foo", 0, 2); List value = jobOperator.getJobInstances("foo", 0, 2); assertEquals(123L, value.get(0).longValue()); } @@ -279,7 +273,7 @@ void testGetLastInstancesSunnyDay() throws Exception { @Test void testGetLastInstancesNoSuchJob() { jobParameters = new JobParameters(); - jobExplorer.getJobInstances("no-such-job", 0, 2); + jobRepository.getJobInstances("no-such-job", 0, 2); assertThrows(NoSuchJobException.class, () -> jobOperator.getJobInstances("no-such-job", 0, 2)); } @@ -291,11 +285,11 @@ public void testGetJobInstanceWithNameAndParameters() { JobInstance jobInstance = mock(); // when - when(this.jobExplorer.getJobInstance(jobName, jobParameters)).thenReturn(jobInstance); + when(this.jobRepository.getJobInstance(jobName, jobParameters)).thenReturn(jobInstance); JobInstance actualJobInstance = this.jobOperator.getJobInstance(jobName, jobParameters); // then - verify(this.jobExplorer).getJobInstance(jobName, jobParameters); + verify(this.jobRepository).getJobInstance(jobName, jobParameters); assertEquals(jobInstance, actualJobInstance); } @@ -309,17 +303,17 @@ void testGetJobNames() { @Test void testGetExecutionsSunnyDay() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); - when(jobExplorer.getJobInstance(123L)).thenReturn(jobInstance); + when(jobRepository.getJobInstance(123L)).thenReturn(jobInstance); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); - when(jobExplorer.getJobExecutions(jobInstance)).thenReturn(Collections.singletonList(jobExecution)); + when(jobRepository.getJobExecutions(jobInstance)).thenReturn(Collections.singletonList(jobExecution)); List value = jobOperator.getExecutions(123L); assertEquals(111L, value.iterator().next().longValue()); } @Test void testGetExecutionsNoSuchInstance() { - jobExplorer.getJobInstance(123L); + jobRepository.getJobInstance(123L); assertThrows(NoSuchJobInstanceException.class, () -> jobOperator.getExecutions(123L)); } @@ -327,8 +321,8 @@ void testGetExecutionsNoSuchInstance() { void testStop() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); - jobExplorer.getJobExecution(111L); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); + jobRepository.getJobExecution(111L); jobRepository.update(jobExecution); jobOperator.stop(111L); assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); @@ -350,10 +344,10 @@ void testStopTasklet() throws Exception { when(step.getTasklet()).thenReturn(tasklet); when(step.getName()).thenReturn("test_job.step1"); when(jobRegistry.getJob(any(String.class))).thenReturn(job); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); jobOperator.setJobRegistry(jobRegistry); - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); jobRepository.update(jobExecution); jobOperator.stop(111L); assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); @@ -369,7 +363,7 @@ void testStopTaskletWhenJobNotRegistered() throws Exception { when(step.getTasklet()).thenReturn(tasklet); when(jobRegistry.getJob(job.getName())).thenThrow(new NoSuchJobException("Unable to find job")); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); jobOperator.setJobRegistry(jobRegistry); jobOperator.stop(111L); @@ -405,10 +399,10 @@ public void stop() { when(step.getTasklet()).thenReturn(tasklet); when(step.getName()).thenReturn("test_job.step1"); when(jobRegistry.getJob(any(String.class))).thenReturn(job); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(111L)).thenReturn(jobExecution); jobOperator.setJobRegistry(jobRegistry); - jobExplorer.getJobExecution(111L); + jobRepository.getJobExecution(111L); jobRepository.update(jobExecution); jobOperator.stop(111L); assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); @@ -419,7 +413,7 @@ void testAbort() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); jobExecution.setStatus(BatchStatus.STOPPING); - when(jobExplorer.getJobExecution(123L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(123L)).thenReturn(jobExecution); jobRepository.update(jobExecution); jobOperator.abandon(123L); assertEquals(BatchStatus.ABANDONED, jobExecution.getStatus()); @@ -431,7 +425,7 @@ void testAbortNonStopping() { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); jobExecution.setStatus(BatchStatus.STARTED); - when(jobExplorer.getJobExecution(123L)).thenReturn(jobExecution); + when(jobRepository.getJobExecution(123L)).thenReturn(jobExecution); jobRepository.update(jobExecution); assertThrows(JobExecutionAlreadyRunningException.class, () -> jobOperator.abandon(123L)); } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml index e6573aa452..d3958ef861 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml @@ -58,7 +58,6 @@ - diff --git a/spring-batch-core/src/test/resources/simple-job-launcher-context.xml b/spring-batch-core/src/test/resources/simple-job-launcher-context.xml index 1dbd4308a4..8bedd42400 100644 --- a/spring-batch-core/src/test/resources/simple-job-launcher-context.xml +++ b/spring-batch-core/src/test/resources/simple-job-launcher-context.xml @@ -21,8 +21,7 @@ + p:jobLauncher-ref="jobLauncher" p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry" /> - - @@ -53,7 +49,6 @@ - diff --git a/spring-batch-samples/src/main/resources/org/springframework/batch/samples/skip/job/skipSample-job-launcher-context.xml b/spring-batch-samples/src/main/resources/org/springframework/batch/samples/skip/job/skipSample-job-launcher-context.xml index 4b78507734..bc9d4bc447 100644 --- a/spring-batch-samples/src/main/resources/org/springframework/batch/samples/skip/job/skipSample-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/org/springframework/batch/samples/skip/job/skipSample-job-launcher-context.xml @@ -14,7 +14,7 @@ p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" /> + p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry" /> diff --git a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml index ee3c50c529..61db4fb2b7 100644 --- a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml @@ -21,8 +21,7 @@ + p:jobLauncher-ref="jobLauncher" p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry" /> Date: Mon, 5 May 2025 18:36:07 +0200 Subject: [PATCH 009/182] Remove JobExplorer bean registration from the default batch configuration Resolves #4825 --- .../annotation/BatchRegistrar.java | 47 ------------------- .../annotation/EnableBatchProcessing.java | 3 -- .../support/DefaultBatchConfiguration.java | 21 --------- .../annotation/BatchRegistrarTests.java | 9 ---- .../DefaultBatchConfigurationTests.java | 3 -- 5 files changed, 83 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java index 631f12b262..d8e58f138f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java @@ -53,8 +53,6 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { private static final String JOB_REPOSITORY = "jobRepository"; - private static final String JOB_EXPLORER = "jobExplorer"; - private static final String JOB_LAUNCHER = "jobLauncher"; private static final String JOB_REGISTRY = "jobRegistry"; @@ -70,7 +68,6 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B .get(EnableBatchProcessing.class) .synthesize(); registerJobRepository(registry, batchAnnotation); - registerJobExplorer(registry, batchAnnotation); registerJobLauncher(registry, batchAnnotation); registerJobRegistry(registry); registerJobRegistrySmartInitializingSingleton(registry); @@ -151,50 +148,6 @@ private void registerJobRepository(BeanDefinitionRegistry registry, EnableBatchP registry.registerBeanDefinition(JOB_REPOSITORY, beanDefinitionBuilder.getBeanDefinition()); } - private void registerJobExplorer(BeanDefinitionRegistry registry, EnableBatchProcessing batchAnnotation) { - if (registry.containsBeanDefinition(JOB_EXPLORER)) { - LOGGER.info("Bean jobExplorer already defined in the application context, skipping" - + " the registration of a jobExplorer"); - return; - } - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder - .genericBeanDefinition(JobExplorerFactoryBean.class); - - // set mandatory properties - String dataSourceRef = batchAnnotation.dataSourceRef(); - beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef); - - String transactionManagerRef = batchAnnotation.transactionManagerRef(); - beanDefinitionBuilder.addPropertyReference("transactionManager", transactionManagerRef); - - // set optional properties - String executionContextSerializerRef = batchAnnotation.executionContextSerializerRef(); - if (registry.containsBeanDefinition(executionContextSerializerRef)) { - beanDefinitionBuilder.addPropertyReference("serializer", executionContextSerializerRef); - } - - String conversionServiceRef = batchAnnotation.conversionServiceRef(); - if (registry.containsBeanDefinition(conversionServiceRef)) { - beanDefinitionBuilder.addPropertyReference("conversionService", conversionServiceRef); - } - - String jobKeyGeneratorRef = batchAnnotation.jobKeyGeneratorRef(); - if (registry.containsBeanDefinition(jobKeyGeneratorRef)) { - beanDefinitionBuilder.addPropertyReference("jobKeyGenerator", jobKeyGeneratorRef); - } - - String charset = batchAnnotation.charset(); - if (charset != null) { - beanDefinitionBuilder.addPropertyValue("charset", Charset.forName(charset)); - } - - String tablePrefix = batchAnnotation.tablePrefix(); - if (tablePrefix != null) { - beanDefinitionBuilder.addPropertyValue("tablePrefix", tablePrefix); - } - registry.registerBeanDefinition(JOB_EXPLORER, beanDefinitionBuilder.getBeanDefinition()); - } - private void registerJobLauncher(BeanDefinitionRegistry registry, EnableBatchProcessing batchAnnotation) { if (registry.containsBeanDefinition(JOB_LAUNCHER)) { LOGGER.info("Bean jobLauncher already defined in the application context, skipping" diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java index 6e2740079d..999706a53a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java @@ -87,9 +87,6 @@ * {@link TaskExecutorJobLauncher}) *

  • a {@link JobRegistry} (bean name "jobRegistry" of type * {@link org.springframework.batch.core.configuration.support.MapJobRegistry})
  • - *
  • a {@link org.springframework.batch.core.explore.JobExplorer} (bean name - * "jobExplorer" of type - * {@link org.springframework.batch.core.explore.support.SimpleJobExplorer})
  • *
  • a {@link org.springframework.batch.core.launch.JobOperator} (bean name * "jobOperator" of type * {@link org.springframework.batch.core.launch.support.SimpleJobOperator})
  • diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java index 1a628b3d93..dea1f33319 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java @@ -79,7 +79,6 @@ * *