mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Align with breaking changes in latest Batch snapshots
Batch is now auto-configured to use the context's PlatformTransactionManager and DataSource or `@BatchDataSource`. When this does not meet the user's needs, they can use `@EnableBatchProcessing` or sub-class `DefaultBatchConfiguration` to take complete control with the auto-configuration backing off. Closes gh-32330
This commit is contained in:
parent
dc56fa62bc
commit
64f4da80cb
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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<DataSource> 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 {
|
||||
|
@ -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<DataSource> batchDataSource,
|
||||
ObjectProvider<TransactionManagerCustomizers> 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<DataSource> batchDataSource,
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
|
||||
EntityManagerFactory entityManagerFactory) {
|
||||
return new JpaBatchConfigurer(properties, batchDataSource.getIfAvailable(() -> dataSource),
|
||||
transactionManagerCustomizers.getIfAvailable(), entityManagerFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user