Fix tests related to infrastructure beans configuration

These tests seem to start failing since 31af573 but were
not caught due to #4121. This commit fixes the tests that
are related to infrastructure beans configuration.

Some other tests seems to have started failing as well but
are not related to this change set. There were temporarily
ignored in this commit and will be addressed separately.

Issue #4121
This commit is contained in:
Mahmoud Ben Hassine
2022-07-13 05:30:37 +02:00
parent 85a9cad193
commit b89ea8e789
11 changed files with 87 additions and 69 deletions

View File

@@ -15,29 +15,26 @@
*/
package org.springframework.batch.core.configuration.annotation;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.support.MapJobRegistry;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
/**
* Base {@code Configuration} class providing common structure for enabling and using
@@ -54,15 +51,17 @@ import org.springframework.util.Assert;
@Import(ScopeConfiguration.class)
public abstract class AbstractBatchConfiguration implements InitializingBean {
private static final Log logger = LogFactory.getLog(AbstractBatchConfiguration.class);
@Autowired
protected ApplicationContext context;
private BatchConfigurer configurer;
private JobBuilderFactory jobBuilderFactory;
private StepBuilderFactory stepBuilderFactory;
private JobRegistry jobRegistry = new MapJobRegistry();
/**
* Establish the {@link JobBuilderFactory} for the batch execution.
* @return The instance of the {@link JobBuilderFactory}.
@@ -114,7 +113,7 @@ public abstract class AbstractBatchConfiguration implements InitializingBean {
*/
@Bean
public JobRegistry jobRegistry() throws Exception {
return new MapJobRegistry();
return this.jobRegistry;
}
/**
@@ -126,55 +125,60 @@ public abstract class AbstractBatchConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
this.jobBuilderFactory = new JobBuilderFactory(jobRepository());
this.stepBuilderFactory = new StepBuilderFactory(jobRepository(), transactionManager());
BatchConfigurer batchConfigurer = getOrCreateConfigurer();
this.jobBuilderFactory = new JobBuilderFactory(batchConfigurer.getJobRepository());
this.stepBuilderFactory = new StepBuilderFactory(batchConfigurer.getJobRepository(),
batchConfigurer.getTransactionManager());
}
/**
* If a {@link BatchConfigurer} exists, return it. If the configurers list is empty,
* create a {@link DefaultBatchConfigurer}. If more than one configurer is present in
* the list, an {@link IllegalStateException} is thrown.
* @param configurers The {@link Collection} of configurers to review.
* If a {@link BatchConfigurer} exists, return it. Otherwise, create a
* {@link DefaultBatchConfigurer}. If more than one configurer is present, an
* {@link IllegalStateException} is thrown.
* @return The {@link BatchConfigurer} that was in the configurers collection or the
* one created.
* default one created.
*/
protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) {
if (this.configurer != null) {
return this.configurer;
protected BatchConfigurer getOrCreateConfigurer() {
BatchConfigurer batchConfigurer = getConfigurer();
if (batchConfigurer == null) {
batchConfigurer = createDefaultConfigurer();
}
if (configurers == null || configurers.isEmpty()) {
DataSource dataSource = getDataSource();
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
configurer.initialize();
this.configurer = configurer;
return this.configurer;
}
if (configurers.size() > 1) {
return batchConfigurer;
}
private BatchConfigurer getConfigurer() {
Map<String, BatchConfigurer> configurers = this.context.getBeansOfType(BatchConfigurer.class);
if (configurers != null && configurers.size() > 1) {
throw new IllegalStateException(
"To use a custom BatchConfigurer the context must contain precisely one, found "
+ configurers.size());
}
this.configurer = configurers.iterator().next();
return this.configurer;
if (configurers != null && configurers.size() == 1) {
return configurers.entrySet().iterator().next().getValue();
}
return null;
}
private BatchConfigurer createDefaultConfigurer() {
DataSource dataSource = getDataSource();
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
configurer.initialize();
return configurer;
}
private DataSource getDataSource() {
DataSource dataSource;
try {
dataSource = this.context.getBean(DataSource.class);
Map<String, DataSource> dataSources = this.context.getBeansOfType(DataSource.class);
if (dataSources == null || (dataSources != null && dataSources.isEmpty())) {
throw new IllegalStateException("To use the default BatchConfigurer, the application context must"
+ " contain at least one data source but none was found.");
}
catch (NoUniqueBeanDefinitionException exception) {
throw new IllegalStateException(
"Multiple data sources are defined in the application context and no primary candidate was found. "
+ "To use the default BatchConfigurer, one of the data sources should be annotated with '@Primary'.",
exception);
if (dataSources != null && dataSources.size() > 1) {
logger.info("Multiple data sources are defined in the application context. The data source to"
+ " use in the default BatchConfigurer will be the one selected by Spring according"
+ " to the rules of getting the primary bean from the application context.");
return this.context.getBean(DataSource.class);
}
catch (NoSuchBeanDefinitionException exception) {
throw new IllegalStateException(
"To use the default BatchConfigurer, the application context must contain at least one data source.",
exception);
}
return dataSource;
return dataSources.entrySet().iterator().next().getValue();
}
}

View File

@@ -25,6 +25,7 @@ import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
@@ -34,7 +35,7 @@ import org.springframework.util.Assert;
* Default implementation of the {@link BatchConfigurer}.
*/
@Component
public class DefaultBatchConfigurer implements BatchConfigurer {
public class DefaultBatchConfigurer implements BatchConfigurer, InitializingBean {
private DataSource dataSource;
@@ -66,6 +67,7 @@ public class DefaultBatchConfigurer implements BatchConfigurer {
Assert.notNull(transactionManager, "transactionManager must not be null");
this.dataSource = dataSource;
this.transactionManager = transactionManager;
initialize();
}
/**
@@ -104,6 +106,11 @@ public class DefaultBatchConfigurer implements BatchConfigurer {
return this.transactionManager;
}
@Override
public void afterPropertiesSet() throws Exception {
initialize();
}
/**
* Initialize the {@link DefaultBatchConfigurer} with the {@link JobRepository},
* {@link JobExplorer}, and {@link JobLauncher}.

View File

@@ -38,30 +38,24 @@ import org.springframework.transaction.PlatformTransactionManager;
@Configuration(proxyBeanMethods = false)
public class SimpleBatchConfiguration extends AbstractBatchConfiguration {
@Autowired(required = false)
private Collection<BatchConfigurer> configurers;
@Override
@Bean
public JobRepository jobRepository() throws Exception {
return getConfigurer(configurers).getJobRepository();
return getOrCreateConfigurer().getJobRepository();
}
@Override
@Bean
public JobLauncher jobLauncher() throws Exception {
return getConfigurer(configurers).getJobLauncher();
return getOrCreateConfigurer().getJobLauncher();
}
@Override
@Bean
public JobExplorer jobExplorer() throws Exception {
return getConfigurer(configurers).getJobExplorer();
return getOrCreateConfigurer().getJobExplorer();
}
@Override
public PlatformTransactionManager transactionManager() throws Exception {
return getConfigurer(configurers).getTransactionManager();
return getOrCreateConfigurer().getTransactionManager();
}
}