BATCH-2537: add support for @Primary annotated data sources
Currently, when multiple data sources are defined in the context, an IllegalStateException is thrown even if one of the data sources is annotated with @Primary (which should be the one to use). This commit makes it possible to use the data source annotated with @Primary when multiple data sources are defined. Note that the context initialization will still fail (with a UnsatisfiedDependencyException from Spring's bean factory) if multiple data sources are defined and none of them is annotated with @Primary. If multiple data sources are defined and none of them is annotated with @Primary but one of them is named "dataSource", this data source will be used by the batch configuration due to autowiring by name (this detail has been documented in the javadoc of @EnableBatchProcessing). Resolves BATCH-2537
This commit is contained in:
committed by
Michael Minella
parent
98add33ab4
commit
7a9a2a9c50
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -41,6 +41,7 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 2.2
|
||||
* @see EnableBatchProcessing
|
||||
*/
|
||||
@@ -49,7 +50,7 @@ import java.util.Collection;
|
||||
public abstract class AbstractBatchConfiguration implements ImportAware {
|
||||
|
||||
@Autowired(required = false)
|
||||
private Collection<DataSource> dataSources;
|
||||
private DataSource dataSource;
|
||||
|
||||
private BatchConfigurer configurer;
|
||||
|
||||
@@ -93,20 +94,16 @@ public abstract class AbstractBatchConfiguration implements ImportAware {
|
||||
return this.configurer;
|
||||
}
|
||||
if (configurers == null || configurers.isEmpty()) {
|
||||
if (dataSources == null || dataSources.isEmpty()) {
|
||||
if (dataSource == null) {
|
||||
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer();
|
||||
configurer.initialize();
|
||||
this.configurer = configurer;
|
||||
return configurer;
|
||||
} else if(dataSources != null && dataSources.size() == 1) {
|
||||
DataSource dataSource = dataSources.iterator().next();
|
||||
} else {
|
||||
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
|
||||
configurer.initialize();
|
||||
this.configurer = configurer;
|
||||
return configurer;
|
||||
} else {
|
||||
throw new IllegalStateException("To use the default BatchConfigurer the context must contain no more than " +
|
||||
"one DataSource, found " + dataSources.size());
|
||||
}
|
||||
}
|
||||
if (configurers.size() > 1) {
|
||||
@@ -144,4 +141,4 @@ class ScopeConfiguration {
|
||||
jobScope.setAutoProxy(false);
|
||||
return jobScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2018 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.
|
||||
@@ -27,6 +27,7 @@ import org.springframework.batch.core.configuration.support.ApplicationContextFa
|
||||
import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@@ -85,7 +86,12 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* </pre>
|
||||
*
|
||||
* If a user does not provide a {@link javax.sql.DataSource} within the context, a Map based
|
||||
* {@link org.springframework.batch.core.repository.JobRepository} will be used.
|
||||
* {@link org.springframework.batch.core.repository.JobRepository} will be used. If multiple
|
||||
* {@link javax.sql.DataSource}s are defined in the context, the one annotated with
|
||||
* {@link org.springframework.context.annotation.Primary} will be used (Note that if none
|
||||
* of them is annotated with {@link org.springframework.context.annotation.Primary}, the one
|
||||
* named <code>dataSource</code> will be used if any, otherwise a {@link UnsatisfiedDependencyException}
|
||||
* will be thrown).
|
||||
*
|
||||
* Note that only one of your configuration classes needs to have the <code>@EnableBatchProcessing</code>
|
||||
* annotation. Once you have an <code>@EnableBatchProcessing</code> class in your configuration you will have an
|
||||
@@ -156,6 +162,7 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* </pre>
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
@@ -33,9 +33,11 @@ import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -57,11 +59,21 @@ public class MapJobRepositoryConfigurationTests {
|
||||
testConfigurationClass(HsqlBatchConfiguration.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testMultipleDataSources() throws Exception {
|
||||
@Test(expected = UnsatisfiedDependencyException.class)
|
||||
public void testMultipleDataSources_whenNoneOfThemIsPrimary() throws Exception {
|
||||
testConfigurationClass(InvalidBatchConfiguration.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleDataSources_whenNoneOfThemIsPrimaryButOneOfThemIsNamed_dataSource_() throws Exception {
|
||||
testConfigurationClass(ValidBatchConfigurationWithoutPrimaryDataSource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleDataSources_whenOneOfThemIsPrimary() throws Exception {
|
||||
testConfigurationClass(ValidBatchConfigurationWithPrimaryDataSource.class);
|
||||
}
|
||||
|
||||
private void testConfigurationClass(Class<?> clazz) throws Exception {
|
||||
GenericApplicationContext context = new AnnotationConfigApplicationContext(clazz);
|
||||
this.jobLauncher = context.getBean(JobLauncher.class);
|
||||
@@ -85,11 +97,37 @@ public class MapJobRepositoryConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ValidBatchConfigurationWithPrimaryDataSource extends HsqlBatchConfiguration {
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
DataSource dataSource2() {
|
||||
return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder().
|
||||
setName("dataSource2").
|
||||
addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql").
|
||||
addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").
|
||||
build());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ValidBatchConfigurationWithoutPrimaryDataSource extends HsqlBatchConfiguration {
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() { // will be autowired by name
|
||||
return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder().
|
||||
setName("dataSource").
|
||||
addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql").
|
||||
addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").
|
||||
build());
|
||||
}
|
||||
}
|
||||
|
||||
public static class HsqlBatchConfiguration extends MapRepositoryBatchConfiguration {
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() {
|
||||
DataSource dataSource1() {
|
||||
return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder().
|
||||
setName("dataSource1").
|
||||
addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql").
|
||||
addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").
|
||||
build());
|
||||
|
||||
Reference in New Issue
Block a user