Merge pull request #17375 from nosan

* gh-17375:
  Polish "Add support for configuring a Batch-specific DataSource"
  Add support for configuring a Batch-specific DataSource

Closes gh-17375
This commit is contained in:
Andy Wilkinson 2019-07-08 14:28:52 +01:00
commit 091cdddc73
5 changed files with 92 additions and 8 deletions

View File

@ -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(DataSource dataSource,
return new BatchDataSourceInitializer(dataSource, resourceLoader, this.properties); @BatchDataSource ObjectProvider<DataSource> batchDataSource, ResourceLoader resourceLoader) {
return new BatchDataSourceInitializer(batchDataSource.getIfAvailable(() -> dataSource), resourceLoader,
this.properties);
} }
@Bean @Bean

View File

@ -45,8 +45,10 @@ class BatchConfigurerConfiguration {
@Bean @Bean
BasicBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, BasicBatchConfigurer batchConfigurer(BatchProperties properties, 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),
transactionManagerCustomizers.getIfAvailable());
} }
} }
@ -58,10 +60,11 @@ class BatchConfigurerConfiguration {
@Bean @Bean
JpaBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, JpaBatchConfigurer batchConfigurer(BatchProperties properties, 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),
entityManagerFactory); transactionManagerCustomizers.getIfAvailable(), entityManagerFactory);
} }
} }

View File

@ -0,0 +1,42 @@
/*
* 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;
import org.springframework.context.annotation.Primary;
/**
* Qualifier annotation for a DataSource to be injected into Batch auto-configuration. Can
* be used on a secondary data source, if there is another one marked as
* {@link Primary @Primary}.
*
* @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 {
}

View File

@ -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 {
}); });
} }
@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 {

View File

@ -2429,9 +2429,13 @@ 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. To
{spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[The have Batch use a `DataSource` other than the applications main `DataSource`, declare a
`DataSource` bean, annotating its `@Bean` method with `@BatchDataSource`. If you do so and
want two data sources, remember to create another one and mark it as `@Primary`. To take
greater control, implement `BatchConfigurer`. See
{spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[the
Javadoc of `@EnableBatchProcessing`] for more details. Javadoc of `@EnableBatchProcessing`] for more details.
For more about Spring Batch, see the https://projects.spring.io/spring-batch/[Spring Batch For more about Spring Batch, see the https://projects.spring.io/spring-batch/[Spring Batch