Commit f449665e authored by Dmytro Nosan's avatar Dmytro Nosan Committed by Andy Wilkinson

Add support for configuring a Batch-specific DataSource

See gh-17375
parent f7850ef8
...@@ -76,8 +76,10 @@ public class BatchAutoConfiguration { ...@@ -76,8 +76,10 @@ public class BatchAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@ConditionalOnBean(DataSource.class) @ConditionalOnBean(DataSource.class)
public BatchDataSourceInitializer batchDataSourceInitializer(DataSource dataSource, ResourceLoader resourceLoader) { public BatchDataSourceInitializer batchDataSourceInitializer(ObjectProvider<DataSource> dataSource,
return new BatchDataSourceInitializer(dataSource, resourceLoader, this.properties); @BatchDataSource ObjectProvider<DataSource> batchDataSource, ResourceLoader resourceLoader) {
return new BatchDataSourceInitializer(batchDataSource.getIfAvailable(dataSource::getIfAvailable),
resourceLoader, this.properties);
} }
@Bean @Bean
......
...@@ -36,6 +36,7 @@ import org.springframework.transaction.PlatformTransactionManager; ...@@ -36,6 +36,7 @@ import org.springframework.transaction.PlatformTransactionManager;
*/ */
@ConditionalOnClass(PlatformTransactionManager.class) @ConditionalOnClass(PlatformTransactionManager.class)
@ConditionalOnMissingBean(BatchConfigurer.class) @ConditionalOnMissingBean(BatchConfigurer.class)
@ConditionalOnBean(DataSource.class)
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
class BatchConfigurerConfiguration { class BatchConfigurerConfiguration {
...@@ -44,9 +45,11 @@ class BatchConfigurerConfiguration { ...@@ -44,9 +45,11 @@ class BatchConfigurerConfiguration {
static class JdbcBatchConfiguration { static class JdbcBatchConfiguration {
@Bean @Bean
BasicBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, BasicBatchConfigurer batchConfigurer(BatchProperties properties, ObjectProvider<DataSource> dataSource,
@BatchDataSource ObjectProvider<DataSource> batchDataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) { ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
return new BasicBatchConfigurer(properties, dataSource, transactionManagerCustomizers.getIfAvailable()); return new BasicBatchConfigurer(properties, batchDataSource.getIfAvailable(dataSource::getIfAvailable),
transactionManagerCustomizers.getIfAvailable());
} }
} }
...@@ -57,11 +60,12 @@ class BatchConfigurerConfiguration { ...@@ -57,11 +60,12 @@ class BatchConfigurerConfiguration {
static class JpaBatchConfiguration { static class JpaBatchConfiguration {
@Bean @Bean
JpaBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, JpaBatchConfigurer batchConfigurer(BatchProperties properties, ObjectProvider<DataSource> dataSource,
@BatchDataSource ObjectProvider<DataSource> batchDataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
EntityManagerFactory entityManagerFactory) { EntityManagerFactory entityManagerFactory) {
return new JpaBatchConfigurer(properties, dataSource, transactionManagerCustomizers.getIfAvailable(), return new JpaBatchConfigurer(properties, batchDataSource.getIfAvailable(dataSource::getIfAvailable),
entityManagerFactory); transactionManagerCustomizers.getIfAvailable(), entityManagerFactory);
} }
} }
......
/*
* Copyright 2012-2019 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 java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Qualifier;
/**
* Qualifier annotation to allow a Batch-specific DataSource.
*
* @author Dmytro Nosan
* @since 2.2.0
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface BatchDataSource {
}
...@@ -49,10 +49,12 @@ import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfigurati ...@@ -49,10 +49,12 @@ import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfigurati
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.test.City; import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode; import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DataSourceTransactionManager;
...@@ -233,6 +235,37 @@ class BatchAutoConfigurationTests { ...@@ -233,6 +235,37 @@ class BatchAutoConfigurationTests {
}); });
} }
@Test
void testBatchDataSource() {
this.contextRunner.withUserConfiguration(TestConfiguration.class, BatchDataSourceConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(BatchConfigurer.class)
.hasSingleBean(BatchDataSourceInitializer.class).hasBean("batchDataSource");
DataSource batchDataSource = context.getBean("batchDataSource", DataSource.class);
assertThat(context.getBean(BatchConfigurer.class)).hasFieldOrPropertyWithValue("dataSource",
batchDataSource);
assertThat(context.getBean(BatchDataSourceInitializer.class))
.hasFieldOrPropertyWithValue("dataSource", batchDataSource);
});
}
@Configuration(proxyBeanMethods = false)
protected static class BatchDataSourceConfiguration {
@Bean
@Primary
public DataSource normalDataSource() {
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:normal").username("sa").build();
}
@BatchDataSource
@Bean
public DataSource batchDataSource() {
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:batchdatasource").username("sa").build();
}
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
static class EmptyConfiguration { static class EmptyConfiguration {
......
...@@ -2429,8 +2429,12 @@ other factory that your application defines, if any. ...@@ -2429,8 +2429,12 @@ other factory that your application defines, if any.
This section answers questions that arise from using Spring Batch with Spring Boot. This section answers questions that arise from using Spring Batch with Spring Boot.
NOTE: By default, batch applications require a `DataSource` to store job details. If you NOTE: By default, batch applications require a `DataSource` to store job details.
want to deviate from that, you need to implement `BatchConfigurer`. See Batch autowires a single `DataSource` in your context and
uses that for processing. If you like to use a different `DataSource`, you can create
one and mark it is `@Bean` as `@BatchDataSource`. If you do so and want two data sources,
remember to create another one and mark it as `@Primary`. If you want to deviate from that,
you need to implement `BatchConfigurer`. See
{spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[The {spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[The
Javadoc of `@EnableBatchProcessing`] for more details. Javadoc of `@EnableBatchProcessing`] for more details.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment