diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java deleted file mode 100644 index 8c35a248f1..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2012-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.boot.autoconfigure.batch; - -import javax.sql.DataSource; - -import org.springframework.batch.core.configuration.annotation.BatchConfigurer; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.autoconfigure.batch.BatchProperties.Isolation; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; -import org.springframework.boot.context.properties.PropertyMapper; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.PlatformTransactionManager; - -/** - * Basic {@link BatchConfigurer} implementation. - * - * @author Dave Syer - * @author Andy Wilkinson - * @author Kazuki Shimizu - * @author Stephane Nicoll - * @since 1.0.0 - */ -public class BasicBatchConfigurer implements BatchConfigurer, InitializingBean { - - private final BatchProperties properties; - - private final DataSource dataSource; - - private final TransactionManagerCustomizers transactionManagerCustomizers; - - private PlatformTransactionManager transactionManager; - - private JobRepository jobRepository; - - private JobLauncher jobLauncher; - - private JobExplorer jobExplorer; - - /** - * Create a new {@link BasicBatchConfigurer} instance. - * @param properties the batch properties - * @param dataSource the underlying data source - * @param transactionManagerCustomizers transaction manager customizers (or - * {@code null}) - */ - protected BasicBatchConfigurer(BatchProperties properties, DataSource dataSource, - TransactionManagerCustomizers transactionManagerCustomizers) { - this.properties = properties; - this.dataSource = dataSource; - this.transactionManagerCustomizers = transactionManagerCustomizers; - } - - @Override - public JobRepository getJobRepository() { - return this.jobRepository; - } - - @Override - public JobLauncher getJobLauncher() { - return this.jobLauncher; - } - - @Override - public JobExplorer getJobExplorer() throws Exception { - return this.jobExplorer; - } - - @Override - public void afterPropertiesSet() { - initialize(); - } - - public void initialize() { - try { - this.jobRepository = createJobRepository(); - this.jobLauncher = createJobLauncher(); - this.jobExplorer = createJobExplorer(); - } - catch (Exception ex) { - throw new IllegalStateException("Unable to initialize Spring Batch", ex); - } - } - - protected JobExplorer createJobExplorer() throws Exception { - PropertyMapper map = PropertyMapper.get(); - JobExplorerFactoryBean factory = new JobExplorerFactoryBean(); - factory.setDataSource(this.dataSource); - map.from(this.properties.getJdbc()::getTablePrefix).whenHasText().to(factory::setTablePrefix); - factory.afterPropertiesSet(); - return factory.getObject(); - } - - protected JobLauncher createJobLauncher() throws Exception { - TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher(); - jobLauncher.setJobRepository(getJobRepository()); - jobLauncher.afterPropertiesSet(); - return jobLauncher; - } - - protected JobRepository createJobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - PropertyMapper map = PropertyMapper.get(); - map.from(this.dataSource).to(factory::setDataSource); - map.from(this::determineIsolationLevel).whenNonNull().to(factory::setIsolationLevelForCreate); - map.from(this.properties.getJdbc()::getTablePrefix).whenHasText().to(factory::setTablePrefix); - map.from(this::buildTransactionManager).to(factory::setTransactionManager); - factory.afterPropertiesSet(); - return factory.getObject(); - } - - /** - * Determine the isolation level for create* operation of the {@link JobRepository}. - * @return the isolation level or {@code null} to use the default - */ - protected String determineIsolationLevel() { - Isolation isolation = this.properties.getJdbc().getIsolationLevelForCreate(); - return (isolation != null) ? isolation.toIsolationName() : null; - } - - protected PlatformTransactionManager createTransactionManager() { - return new DataSourceTransactionManager(this.dataSource); - } - - private PlatformTransactionManager buildTransactionManager() { - PlatformTransactionManager transactionManager = createTransactionManager(); - if (this.transactionManagerCustomizers != null) { - this.transactionManagerCustomizers.customize(transactionManager); - } - this.transactionManager = transactionManager; - return transactionManager; - } - - PlatformTransactionManager getTransactionManager() { - return this.transactionManager; - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java index a28f21de34..209b8bd187 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.batch; import javax.sql.DataSource; import org.springframework.batch.core.configuration.ListableJobLocator; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration; import org.springframework.batch.core.converter.JobParametersConverter; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; @@ -35,6 +37,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; +import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; import org.springframework.context.annotation.Bean; @@ -42,6 +45,8 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.init.DatabasePopulator; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Isolation; import org.springframework.util.StringUtils; /** @@ -60,11 +65,12 @@ import org.springframework.util.StringUtils; * @author Mahmoud Ben Hassine * @since 1.0.0 */ -@AutoConfiguration(after = HibernateJpaAutoConfiguration.class) +@AutoConfiguration(after = { HibernateJpaAutoConfiguration.class, TransactionAutoConfiguration.class }) @ConditionalOnClass({ JobLauncher.class, DataSource.class, DatabasePopulator.class }) -@ConditionalOnBean({ DataSource.class, JobLauncher.class }) +@ConditionalOnBean({ DataSource.class, PlatformTransactionManager.class }) +@ConditionalOnMissingBean(value = DefaultBatchConfiguration.class, annotation = EnableBatchProcessing.class) @EnableConfigurationProperties(BatchProperties.class) -@Import({ BatchConfigurerConfiguration.class, DatabaseInitializationDependencyConfigurer.class }) +@Import(DatabaseInitializationDependencyConfigurer.class) public class BatchAutoConfiguration { @Bean @@ -100,6 +106,46 @@ public class BatchAutoConfiguration { return factory; } + @Configuration(proxyBeanMethods = false) + static class SpringBootBatchConfiguration extends DefaultBatchConfiguration { + + private final DataSource dataSource; + + private final PlatformTransactionManager transactionManager; + + private final BatchProperties properties; + + SpringBootBatchConfiguration(DataSource dataSource, @BatchDataSource ObjectProvider batchDataSource, + PlatformTransactionManager transactionManager, BatchProperties properties) { + this.dataSource = batchDataSource.getIfAvailable(() -> dataSource); + this.transactionManager = transactionManager; + this.properties = properties; + } + + @Override + protected DataSource getDataSource() { + return this.dataSource; + } + + @Override + protected PlatformTransactionManager getTransactionManager() { + return this.transactionManager; + } + + @Override + protected String getTablePrefix() { + String tablePrefix = this.properties.getJdbc().getTablePrefix(); + return (tablePrefix != null) ? tablePrefix : super.getTablePrefix(); + } + + @Override + protected Isolation getIsolationLevelForCreate() { + Isolation isolation = this.properties.getJdbc().getIsolationLevelForCreate(); + return (isolation != null) ? isolation : super.getIsolationLevelForCreate(); + } + + } + @Configuration(proxyBeanMethods = false) @Conditional(OnBatchDatasourceInitializationCondition.class) static class DataSourceInitializerConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchConfigurerConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchConfigurerConfiguration.java deleted file mode 100644 index d5f62d6981..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchConfigurerConfiguration.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-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.boot.autoconfigure.batch; - -import javax.sql.DataSource; - -import jakarta.persistence.EntityManagerFactory; - -import org.springframework.batch.core.configuration.annotation.BatchConfigurer; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.PlatformTransactionManager; - -/** - * Provide a {@link BatchConfigurer} according to the current environment. - * - * @author Stephane Nicoll - */ -@ConditionalOnClass(PlatformTransactionManager.class) -@ConditionalOnBean(DataSource.class) -@ConditionalOnMissingBean(BatchConfigurer.class) -@Configuration(proxyBeanMethods = false) -class BatchConfigurerConfiguration { - - @Configuration(proxyBeanMethods = false) - @ConditionalOnMissingBean(name = "entityManagerFactory") - static class JdbcBatchConfiguration { - - @Bean - BasicBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, - @BatchDataSource ObjectProvider batchDataSource, - ObjectProvider transactionManagerCustomizers) { - return new BasicBatchConfigurer(properties, batchDataSource.getIfAvailable(() -> dataSource), - transactionManagerCustomizers.getIfAvailable()); - } - - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(EntityManagerFactory.class) - @ConditionalOnBean(name = "entityManagerFactory") - static class JpaBatchConfiguration { - - @Bean - JpaBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, - @BatchDataSource ObjectProvider batchDataSource, - ObjectProvider transactionManagerCustomizers, - EntityManagerFactory entityManagerFactory) { - return new JpaBatchConfigurer(properties, batchDataSource.getIfAvailable(() -> dataSource), - transactionManagerCustomizers.getIfAvailable(), entityManagerFactory); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java index 2422b3b42f..0f40b7807e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.batch; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.sql.init.DatabaseInitializationMode; +import org.springframework.transaction.annotation.Isolation; /** * Configuration properties for Spring Batch. @@ -135,45 +136,4 @@ public class BatchProperties { } - /** - * Available transaction isolation levels. - */ - public enum Isolation { - - /** - * Use the default isolation level of the underlying datastore. - */ - DEFAULT, - - /** - * Indicates that dirty reads, non-repeatable reads and phantom reads can occur. - */ - READ_UNCOMMITTED, - - /** - * Indicates that dirty reads are prevented; non-repeatable reads and phantom - * reads can occur. - */ - READ_COMMITTED, - - /** - * Indicates that dirty reads and non-repeatable reads are prevented; phantom - * reads can occur. - */ - REPEATABLE_READ, - - /** - * Indicate that dirty reads, non-repeatable reads and phantom reads are - * prevented. - */ - SERIALIZABLE; - - private static final String PREFIX = "ISOLATION_"; - - String toIsolationName() { - return PREFIX + name(); - } - - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JpaBatchConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JpaBatchConfigurer.java deleted file mode 100644 index 41da09ca18..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JpaBatchConfigurer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012-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.boot.autoconfigure.batch; - -import javax.sql.DataSource; - -import jakarta.persistence.EntityManagerFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.autoconfigure.batch.BatchProperties.Isolation; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.transaction.PlatformTransactionManager; - -/** - * A {@link BasicBatchConfigurer} tailored for JPA. - * - * @author Stephane Nicoll - * @since 2.0.0 - */ -public class JpaBatchConfigurer extends BasicBatchConfigurer { - - private static final Log logger = LogFactory.getLog(JpaBatchConfigurer.class); - - private final EntityManagerFactory entityManagerFactory; - - /** - * Create a new {@link BasicBatchConfigurer} instance. - * @param properties the batch properties - * @param dataSource the underlying data source - * @param transactionManagerCustomizers transaction manager customizers (or - * {@code null}) - * @param entityManagerFactory the entity manager factory (or {@code null}) - */ - protected JpaBatchConfigurer(BatchProperties properties, DataSource dataSource, - TransactionManagerCustomizers transactionManagerCustomizers, EntityManagerFactory entityManagerFactory) { - super(properties, dataSource, transactionManagerCustomizers); - this.entityManagerFactory = entityManagerFactory; - } - - @Override - protected String determineIsolationLevel() { - String name = super.determineIsolationLevel(); - if (name != null) { - return name; - } - else { - logger.warn("JPA does not support custom isolation levels, so locks may not be taken when launching Jobs. " - + "To silence this warning, set 'spring.batch.jdbc.isolation-level-for-create' to 'default'."); - return Isolation.DEFAULT.toIsolationName(); - } - } - - @Override - protected PlatformTransactionManager createTransactionManager() { - return new JpaTransactionManager(this.entityManagerFactory); - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index b248d5cd7d..bcd01a7ea1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -34,8 +34,8 @@ import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.DuplicateJobException; import org.springframework.batch.core.configuration.JobFactory; import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.batch.core.configuration.annotation.BatchConfigurer; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration; import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.job.AbstractJob; @@ -49,21 +49,23 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.DefaultApplicationArguments; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; +import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration.SpringBootBatchConfiguration; import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; +import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.test.City; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; +import org.springframework.boot.logging.LogLevel; import org.springframework.boot.sql.init.DatabaseInitializationMode; import org.springframework.boot.sql.init.DatabaseInitializationSettings; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -92,11 +94,13 @@ import static org.mockito.Mockito.mock; class BatchAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(BatchAutoConfiguration.class, TransactionAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(BatchAutoConfiguration.class, TransactionAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class)); @Test void testDefaultContext() { - this.contextRunner.withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class) + this.contextRunner.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO)) + .withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class) .run((context) -> { assertThat(context).hasSingleBean(JobLauncher.class); assertThat(context).hasSingleBean(JobExplorer.class); @@ -107,15 +111,6 @@ class BatchAutoConfigurationTests { }); } - @Test - void testNoBatchConfiguration() { - this.contextRunner.withUserConfiguration(EmptyConfiguration.class, EmbeddedDataSourceConfiguration.class) - .run((context) -> { - assertThat(context).doesNotHaveBean(JobLauncher.class); - assertThat(context).doesNotHaveBean(JobRepository.class); - }); - } - @Test void autoconfigurationBacksOffEntirelyIfSpringJdbcAbsent() { this.contextRunner.withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class) @@ -125,6 +120,21 @@ class BatchAutoConfigurationTests { }); } + @Test + void autoConfigurationBacksOffWhenUserEnablesBatchProcessing() { + this.contextRunner + .withUserConfiguration(EnableBatchProcessingConfiguration.class, EmbeddedDataSourceConfiguration.class) + .withClassLoader(new FilteredClassLoader(DatabasePopulator.class)) + .run((context) -> assertThat(context).doesNotHaveBean(SpringBootBatchConfiguration.class)); + } + + @Test + void autoConfigurationBacksOffWhenUserProvidesBatchConfiguration() { + this.contextRunner.withUserConfiguration(CustomBatchConfiguration.class, EmbeddedDataSourceConfiguration.class) + .withClassLoader(new FilteredClassLoader(DatabasePopulator.class)) + .run((context) -> assertThat(context).doesNotHaveBean(SpringBootBatchConfiguration.class)); + } + @Test void testDefinesAndLaunchesJob() { this.contextRunner.withUserConfiguration(JobConfiguration.class, EmbeddedDataSourceConfiguration.class) @@ -254,30 +264,6 @@ class BatchAutoConfigurationTests { }); } - @Test - void testDefaultIsolationLevelWithJpaLogsWarning(CapturedOutput output) { - this.contextRunner.withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class, - HibernateJpaAutoConfiguration.class).run((context) -> { - assertThat(context.getBean(BasicBatchConfigurer.class).determineIsolationLevel()) - .isEqualTo("ISOLATION_DEFAULT"); - assertThat(output).contains("JPA does not support custom isolation levels") - .contains("set 'spring.batch.jdbc.isolation-level-for-create' to 'default'"); - }); - } - - @Test - void testCustomIsolationLevelWithJpaDoesNotLogWarning(CapturedOutput output) { - this.contextRunner.withPropertyValues("spring.batch.jdbc.isolation-level-for-create=default") - .withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class, - HibernateJpaAutoConfiguration.class) - .run((context) -> { - assertThat(context.getBean(BasicBatchConfigurer.class).determineIsolationLevel()) - .isEqualTo("ISOLATION_DEFAULT"); - assertThat(output).doesNotContain("JPA does not support custom isolation levels") - .doesNotContain("set 'spring.batch.jdbc.isolation-level-for-create' to 'default'"); - }); - } - @Test void testRenamePrefix() { this.contextRunner @@ -307,9 +293,9 @@ class BatchAutoConfigurationTests { .withPropertyValues("spring.transaction.default-timeout:30", "spring.transaction.rollback-on-commit-failure:true") .run((context) -> { - assertThat(context).hasSingleBean(BatchConfigurer.class); + assertThat(context).hasSingleBean(BatchAutoConfiguration.class); JpaTransactionManager transactionManager = JpaTransactionManager.class - .cast(context.getBean(BasicBatchConfigurer.class).getTransactionManager()); + .cast(context.getBean(SpringBootBatchConfiguration.class).getTransactionManager()); assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); }); @@ -321,9 +307,9 @@ class BatchAutoConfigurationTests { .withPropertyValues("spring.transaction.default-timeout:30", "spring.transaction.rollback-on-commit-failure:true") .run((context) -> { - assertThat(context).hasSingleBean(BatchConfigurer.class); + assertThat(context).hasSingleBean(SpringBootBatchConfiguration.class); DataSourceTransactionManager transactionManager = DataSourceTransactionManager.class - .cast(context.getBean(BasicBatchConfigurer.class).getTransactionManager()); + .cast(context.getBean(SpringBootBatchConfiguration.class).getTransactionManager()); assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); }); @@ -333,11 +319,11 @@ class BatchAutoConfigurationTests { void testBatchDataSource() { this.contextRunner.withUserConfiguration(TestConfiguration.class, BatchDataSourceConfiguration.class) .run((context) -> { - assertThat(context).hasSingleBean(BatchConfigurer.class) + assertThat(context).hasSingleBean(SpringBootBatchConfiguration.class) .hasSingleBean(BatchDataSourceScriptDatabaseInitializer.class).hasBean("batchDataSource"); DataSource batchDataSource = context.getBean("batchDataSource", DataSource.class); - assertThat(context.getBean(BasicBatchConfigurer.class)).hasFieldOrPropertyWithValue("dataSource", - batchDataSource); + assertThat(context.getBean(SpringBootBatchConfiguration.class).getDataSource()) + .isEqualTo(batchDataSource); assertThat(context.getBean(BatchDataSourceScriptDatabaseInitializer.class)) .hasFieldOrPropertyWithValue("dataSource", batchDataSource); }); @@ -428,7 +414,6 @@ class BatchAutoConfigurationTests { } - @EnableBatchProcessing @TestAutoConfigurationPackage(City.class) static class TestConfiguration { @@ -445,7 +430,6 @@ class BatchAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @EnableBatchProcessing static class NamedJobConfigurationWithRegisteredAndLocalJob { @Autowired @@ -492,7 +476,6 @@ class BatchAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @EnableBatchProcessing static class NamedJobConfigurationWithRegisteredJob { @Bean @@ -561,7 +544,6 @@ class BatchAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @EnableBatchProcessing static class NamedJobConfigurationWithLocalJob { @Autowired @@ -593,7 +575,6 @@ class BatchAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @EnableBatchProcessing static class MultipleJobConfiguration { @Autowired @@ -630,7 +611,6 @@ class BatchAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @EnableBatchProcessing static class JobConfiguration { @Autowired @@ -681,4 +661,15 @@ class BatchAutoConfigurationTests { } + @Configuration(proxyBeanMethods = false) + static class CustomBatchConfiguration extends DefaultBatchConfiguration { + + } + + @EnableBatchProcessing + @Configuration(proxyBeanMethods = false) + static class EnableBatchProcessingConfiguration { + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationWithoutJpaTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationWithoutJpaTests.java index a98511fc4d..dd133a1774 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationWithoutJpaTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationWithoutJpaTests.java @@ -21,12 +21,13 @@ import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; +import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration.SpringBootBatchConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener; import org.springframework.boot.autoconfigure.orm.jpa.test.City; @@ -36,6 +37,7 @@ import org.springframework.boot.sql.init.DatabaseInitializationMode; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.testsupport.classpath.ClassPathExclusions; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.transaction.annotation.Isolation; import static org.assertj.core.api.Assertions.assertThat; @@ -48,7 +50,8 @@ import static org.assertj.core.api.Assertions.assertThat; class BatchAutoConfigurationWithoutJpaTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(BatchAutoConfiguration.class, TransactionAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(BatchAutoConfiguration.class, TransactionAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class)); @Test void jdbcWithDefaultSettings() { @@ -60,7 +63,6 @@ class BatchAutoConfigurationWithoutJpaTests { assertThat(context).hasSingleBean(JobRepository.class); assertThat(context.getBean(BatchProperties.class).getJdbc().getInitializeSchema()) .isEqualTo(DatabaseInitializationMode.EMBEDDED); - assertThat(context.getBean(BasicBatchConfigurer.class).determineIsolationLevel()).isNull(); assertThat(new JdbcTemplate(context.getBean(DataSource.class)) .queryForList("select * from BATCH_JOB_EXECUTION")).isEmpty(); assertThat(context.getBean(JobExplorer.class).findRunningJobExecutions("test")).isEmpty(); @@ -89,11 +91,11 @@ class BatchAutoConfigurationWithoutJpaTests { this.contextRunner.withUserConfiguration(DefaultConfiguration.class, EmbeddedDataSourceConfiguration.class) .withPropertyValues("spring.datasource.generate-unique-name=true", "spring.batch.jdbc.isolation-level-for-create=read_committed") - .run((context) -> assertThat(context.getBean(BasicBatchConfigurer.class).determineIsolationLevel()) - .isEqualTo("ISOLATION_READ_COMMITTED")); + .run((context) -> assertThat( + context.getBean(SpringBootBatchConfiguration.class).getIsolationLevelForCreate()) + .isEqualTo(Isolation.READ_COMMITTED)); } - @EnableBatchProcessing @TestAutoConfigurationPackage(City.class) static class DefaultConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunnerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunnerTests.java index 4cc83d59b5..0c42538d69 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunnerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunnerTests.java @@ -43,7 +43,6 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.sql.init.DatabaseInitializationSettings; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -221,14 +220,13 @@ class JobLauncherApplicationRunnerTests { } - @Configuration(proxyBeanMethods = false) @EnableBatchProcessing - static class BatchConfiguration extends BasicBatchConfigurer { + @Configuration(proxyBeanMethods = false) + static class BatchConfiguration { private final DataSource dataSource; protected BatchConfiguration(DataSource dataSource) { - super(new BatchProperties(), dataSource, new TransactionManagerCustomizers(null)); this.dataSource = dataSource; } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-batch/src/main/java/smoketest/batch/SampleBatchApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-batch/src/main/java/smoketest/batch/SampleBatchApplication.java index c6a123db8c..dd5876d3ab 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-batch/src/main/java/smoketest/batch/SampleBatchApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-batch/src/main/java/smoketest/batch/SampleBatchApplication.java @@ -18,7 +18,6 @@ package smoketest.batch; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -30,7 +29,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.transaction.PlatformTransactionManager; @SpringBootApplication -@EnableBatchProcessing public class SampleBatchApplication { @Bean