diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBean.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBean.java
index dbbd850369..3256c97795 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBean.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBean.java
@@ -25,6 +25,7 @@ import java.lang.annotation.Target;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@@ -69,30 +70,37 @@ public @interface ConditionalOnBean {
/**
* The class types of beans that should be checked. The condition matches when beans
* of all classes specified are contained in the {@link BeanFactory}. Beans that are
- * not autowire candidates are ignored.
+ * not autowire candidates or that are not default candidates are ignored.
* @return the class types of beans to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
Class>[] value() default {};
/**
* The class type names of beans that should be checked. The condition matches when
* beans of all classes specified are contained in the {@link BeanFactory}. Beans that
- * are not autowire candidates are ignored.
+ * are not autowire candidates or that are not default candidates are ignored.
* @return the class type names of beans to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
String[] type() default {};
/**
* The annotation type decorating a bean that should be checked. The condition matches
* when all the annotations specified are defined on beans in the {@link BeanFactory}.
- * Beans that are not autowire candidates are ignored.
+ * Beans that are not autowire candidates or that are not default candidates are
+ * ignored.
* @return the class-level annotation types to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
Class extends Annotation>[] annotation() default {};
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.java
index 60f721f241..be71a1adac 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.java
@@ -25,6 +25,7 @@ import java.lang.annotation.Target;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@@ -70,20 +71,24 @@ public @interface ConditionalOnMissingBean {
/**
* The class types of beans that should be checked. The condition matches when no bean
* of each class specified is contained in the {@link BeanFactory}. Beans that are not
- * autowire candidates are ignored.
+ * autowire candidates or that are not default candidates are ignored.
* @return the class types of beans to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
Class>[] value() default {};
/**
* The class type names of beans that should be checked. The condition matches when no
* bean of each class specified is contained in the {@link BeanFactory}. Beans that
- * are not autowire candidates are ignored.
+ * are not autowire candidates or that are not default candidates are ignored.
* @return the class type names of beans to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
String[] type() default {};
@@ -105,10 +110,13 @@ public @interface ConditionalOnMissingBean {
/**
* The annotation type decorating a bean that should be checked. The condition matches
* when each annotation specified is missing from all beans in the
- * {@link BeanFactory}. Beans that are not autowire candidates are ignored.
+ * {@link BeanFactory}. Beans that are not autowire candidates or that are not default
+ * candidates are ignored.
* @return the class-level annotation types to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
Class extends Annotation>[] annotation() default {};
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.java
index 43866f3ceb..cb99322311 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.java
@@ -24,6 +24,7 @@ import java.lang.annotation.Target;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
@@ -53,14 +54,16 @@ public @interface ConditionalOnSingleCandidate {
/**
* The class type of bean that should be checked. The condition matches if a bean of
* the class specified is contained in the {@link BeanFactory} and a primary candidate
- * exists in case of multiple instances. Beans that are not autowire candidates are
- * ignored.
+ * exists in case of multiple instances. Beans that are not autowire candidates or
+ * that are not default candidates are ignored.
*
* This attribute may not be used in conjunction with
* {@link #type()}, but it may be used instead of {@link #type()}.
* @return the class type of the bean to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
Class> value() default Object.class;
@@ -68,13 +71,15 @@ public @interface ConditionalOnSingleCandidate {
* The class type name of bean that should be checked. The condition matches if a bean
* of the class specified is contained in the {@link BeanFactory} and a primary
* candidate exists in case of multiple instances. Beans that are not autowire
- * candidates are ignored.
+ * candidates or that are not default candidates are ignored.
*
* This attribute may not be used in conjunction with
* {@link #value()}, but it may be used instead of {@link #value()}.
* @return the class type name of the bean to check
* @see Bean#autowireCandidate()
* @see BeanDefinition#isAutowireCandidate
+ * @see Bean#defaultCandidate()
+ * @see AbstractBeanDefinition#isDefaultCandidate
*/
String type() default "";
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
index 14478d14ee..dc73aaf572 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
@@ -42,6 +42,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.context.annotation.Bean;
@@ -217,8 +218,8 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
Map typeMatchedDefinitions = getBeanDefinitionsForType(classLoader,
considerHierarchy, beanFactory, type, parameterizedContainers);
Set typeMatchedNames = matchedNamesFrom(typeMatchedDefinitions,
- (name, definition) -> !beansIgnoredByType.contains(name) && !ScopedProxyUtils.isScopedTarget(name)
- && (definition == null || definition.isAutowireCandidate()));
+ (name, definition) -> isCandidate(name, definition, beansIgnoredByType)
+ && !ScopedProxyUtils.isScopedTarget(name));
if (typeMatchedNames.isEmpty()) {
result.recordUnmatchedType(type);
}
@@ -230,8 +231,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
Map annotationMatchedDefinitions = getBeanDefinitionsForAnnotation(classLoader,
beanFactory, annotation, considerHierarchy);
Set annotationMatchedNames = matchedNamesFrom(annotationMatchedDefinitions,
- (name, definition) -> !beansIgnoredByType.contains(name)
- && (definition == null || definition.isAutowireCandidate()));
+ (name, definition) -> isCandidate(name, definition, beansIgnoredByType));
if (annotationMatchedNames.isEmpty()) {
result.recordUnmatchedAnnotation(annotation);
}
@@ -262,6 +262,18 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return matchedNames;
}
+ private boolean isCandidate(String name, BeanDefinition definition, Set ignoredBeans) {
+ return (!ignoredBeans.contains(name))
+ && (definition == null || (definition.isAutowireCandidate() && isDefaultCandidate(definition)));
+ }
+
+ private boolean isDefaultCandidate(BeanDefinition definition) {
+ if (definition instanceof AbstractBeanDefinition abstractBeanDefinition) {
+ return abstractBeanDefinition.isDefaultCandidate();
+ }
+ return true;
+ }
+
private Set getNamesOfBeansIgnoredByType(ClassLoader classLoader, ListableBeanFactory beanFactory,
boolean considerHierarchy, Set ignoredTypes, Set> parameterizedContainers) {
Set result = null;
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java
index aa6729914d..5b2d540ca4 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java
@@ -261,6 +261,25 @@ class ConditionalOnBeanTests {
.run((context) -> assertThat(context).doesNotHaveBean("bar"));
}
+ @Test
+ void conditionalOnBeanTypeIgnoresNotDefaultCandidateBean() {
+ this.contextRunner.withUserConfiguration(NotDefaultCandidateConfiguration.class, OnBeanClassConfiguration.class)
+ .run((context) -> assertThat(context).doesNotHaveBean("bar"));
+ }
+
+ @Test
+ void conditionalOnBeanNameMatchesNotDefaultCandidateBean() {
+ this.contextRunner.withUserConfiguration(NotDefaultCandidateConfiguration.class, OnBeanNameConfiguration.class)
+ .run((context) -> assertThat(context).hasBean("bar"));
+ }
+
+ @Test
+ void conditionalOnAnnotatedBeanIgnoresNotDefaultCandidateBean() {
+ this.contextRunner
+ .withUserConfiguration(AnnotatedNotDefaultCandidateConfig.class, OnAnnotationConfiguration.class)
+ .run((context) -> assertThat(context).doesNotHaveBean("bar"));
+ }
+
private Consumer exampleBeanRequirement(String... names) {
return (context) -> {
String[] beans = context.getBeanNamesForType(ExampleBean.class);
@@ -356,6 +375,16 @@ class ConditionalOnBeanTests {
}
+ @Configuration(proxyBeanMethods = false)
+ static class NotDefaultCandidateConfiguration {
+
+ @Bean(defaultCandidate = false)
+ String foo() {
+ return "foo";
+ }
+
+ }
+
@Configuration(proxyBeanMethods = false)
@ImportResource("org/springframework/boot/autoconfigure/condition/foo.xml")
static class XmlConfiguration {
@@ -569,6 +598,16 @@ class ConditionalOnBeanTests {
}
+ @Configuration(proxyBeanMethods = false)
+ static class AnnotatedNotDefaultCandidateConfig {
+
+ @Bean(defaultCandidate = false)
+ ExampleBean exampleBean() {
+ return new ExampleBean("value");
+ }
+
+ }
+
@TestAnnotation
static class ExampleBean {
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java
index 5374d9dca9..830f2c17fc 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java
@@ -363,6 +363,25 @@ class ConditionalOnMissingBeanTests {
.run((context) -> assertThat(context).hasBean("bar"));
}
+ @Test
+ void typeBasedMatchingIgnoresBeanThatIsNotDefaultCandidate() {
+ this.contextRunner.withUserConfiguration(NotDefaultCandidateConfig.class, OnBeanTypeConfiguration.class)
+ .run((context) -> assertThat(context).hasBean("bar"));
+ }
+
+ @Test
+ void nameBasedMatchingConsidersBeanThatIsNotDefaultCandidate() {
+ this.contextRunner.withUserConfiguration(NotDefaultCandidateConfig.class, OnBeanNameConfiguration.class)
+ .run((context) -> assertThat(context).doesNotHaveBean("bar"));
+ }
+
+ @Test
+ void annotationBasedMatchingIgnoresBeanThatIsNotDefaultCandidateBean() {
+ this.contextRunner
+ .withUserConfiguration(AnnotatedNotDefaultCandidateConfig.class, OnAnnotationConfiguration.class)
+ .run((context) -> assertThat(context).hasBean("bar"));
+ }
+
private Consumer exampleBeanRequirement(String... names) {
return (context) -> {
String[] beans = context.getBeanNamesForType(ExampleBean.class);
@@ -607,6 +626,16 @@ class ConditionalOnMissingBeanTests {
}
+ @Configuration(proxyBeanMethods = false)
+ static class NotDefaultCandidateConfig {
+
+ @Bean(defaultCandidate = false)
+ String foo() {
+ return "foo";
+ }
+
+ }
+
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = "foo")
static class HierarchyConsidered {
@@ -780,6 +809,16 @@ class ConditionalOnMissingBeanTests {
}
+ @Configuration(proxyBeanMethods = false)
+ static class AnnotatedNotDefaultCandidateConfig {
+
+ @Bean(autowireCandidate = false)
+ ExampleBean exampleBean() {
+ return new ExampleBean("value");
+ }
+
+ }
+
@TestAnnotation
static class ExampleBean {
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java
index 2c268d75bf..6cb9bad7c9 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java
@@ -184,6 +184,17 @@ class ConditionalOnSingleCandidateTests {
});
}
+ @Test
+ void singleCandidateMultipleCandidatesOneDefaultCandidate() {
+ this.contextRunner
+ .withUserConfiguration(AlphaConfiguration.class, BravoNonDefaultConfiguration.class,
+ OnBeanSingleCandidateConfiguration.class)
+ .run((context) -> {
+ assertThat(context).hasBean("consumer");
+ assertThat(context.getBean("consumer")).isEqualTo("alpha");
+ });
+ }
+
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(String.class)
static class OnBeanSingleCandidateConfiguration {
@@ -303,4 +314,14 @@ class ConditionalOnSingleCandidateTests {
}
+ @Configuration(proxyBeanMethods = false)
+ static class BravoNonDefaultConfiguration {
+
+ @Bean(defaultCandidate = false)
+ String bravo() {
+ return "bravo";
+ }
+
+ }
+
}
diff --git a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-access.adoc b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-access.adoc
index a85f619178..36d89cd965 100644
--- a/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-access.adoc
+++ b/spring-boot-project/spring-boot-docs/src/docs/antora/modules/how-to/pages/data-access.adoc
@@ -110,43 +110,41 @@ See xref:reference:data/sql.adoc#data.sql.datasource[] in the "`Spring Boot Feat
[[howto.data-access.configure-two-datasources]]
== Configure Two DataSources
-If you need to configure multiple data sources, you can apply the same tricks that were described in the previous section.
-You must, however, mark one of the `DataSource` instances as `@Primary`, because various auto-configurations down the road expect to be able to get one by type.
+To define an additional `DataSource`, an approach that's similar to the previous section can be used.
+A key difference is that the `DataSource` `@Bean` must be declared with `defaultCandidate=false`.
+This prevents the auto-configured `DataSource` from backing off.
+To allow the additional `DataSource` to be injected where it's needed, also annotate it with `@Qualifier` as shown in the following example:
-If you create your own `DataSource`, the auto-configuration backs off.
-In the following example, we provide the _exact_ same feature set as the auto-configuration provides on the primary data source:
+include-code::MyAdditionalDataSourceConfiguration[]
-include-code::MyDataSourcesConfiguration[]
+To consume the additional `DataSource`, annotate the injection point with the same `@Qualifier`.
-TIP: `firstDataSourceProperties` has to be flagged as `@Primary` so that the database initializer feature uses your copy (if you use the initializer).
-
-Both data sources are also bound for advanced customizations.
-For instance, you could configure them as follows:
+The auto-configured and additional data sources can be configured as follows:
[configprops%novalidate,yaml]
----
+spring:
+ datasource:
+ url: "jdbc:mysql://localhost/first"
+ username: "dbuser"
+ password: "dbpass"
+ configuration:
+ maximum-pool-size: 30
app:
datasource:
- first:
- url: "jdbc:mysql://localhost/first"
- username: "dbuser"
- password: "dbpass"
- configuration:
- maximum-pool-size: 30
-
- second:
- url: "jdbc:mysql://localhost/second"
- username: "dbuser"
- password: "dbpass"
- max-total: 30
+ url: "jdbc:mysql://localhost/second"
+ username: "dbuser"
+ password: "dbpass"
+ max-total: 30
----
-You can apply the same concept to the secondary `DataSource` as well, as shown in the following example:
+More advanced, implementation-specific, configuration of the auto-configured `DataSource` is available through the `spring.datasource.configuration.*` properties.
+You can apply the same concept to the additional `DataSource` as well, as shown in the following example:
-include-code::MyCompleteDataSourcesConfiguration[]
+include-code::MyCompleteAdditionalDataSourceConfiguration[]
-The preceding example configures two data sources on custom namespaces with the same logic as Spring Boot would use in auto-configuration.
-Note that each `configuration` sub namespace provides advanced settings based on the chosen implementation.
+The preceding example configures the additional data source with the same logic as Spring Boot would use in auto-configuration.
+Note that the `app.datasource.configuration.*` properties provide advanced settings based on the chosen implementation.
@@ -295,26 +293,28 @@ You can disable or tune this behavior by registering a `HibernatePropertiesCusto
To take full control of the configuration of the `EntityManagerFactory`, you need to add a `@Bean` named '`entityManagerFactory`'.
Spring Boot auto-configuration switches off its entity manager in the presence of a bean of that type.
+NOTE: When you create a bean for `LocalContainerEntityManagerFactoryBean` yourself, any customization that was applied during the creation of the auto-configured `LocalContainerEntityManagerFactoryBean` is lost.
+Make sure to use the auto-configured `EntityManagerFactoryBuilder` to retain JPA and vendor properties.
+This is particularly important if you were relying on `spring.jpa.*` properties for configuring things like the naming strategy or the DDL mode.
+
[[howto.data-access.use-multiple-entity-managers]]
== Using Multiple EntityManagerFactories
-If you need to use JPA against multiple data sources, you likely need one `EntityManagerFactory` per data source.
+If you need to use JPA against multiple datasources, you likely need one `EntityManagerFactory` per datasource.
The `LocalContainerEntityManagerFactoryBean` from Spring ORM allows you to configure an `EntityManagerFactory` for your needs.
-You can also reuse `JpaProperties` to bind settings for each `EntityManagerFactory`, as shown in the following example:
+You can also reuse `JpaProperties` to bind settings for a second `EntityManagerFactory`.
+Building upon xref:how-to:data-access.adoc#howto.data-access.configure-two-datasources[the example for configuring a second `DataSource`], a second `EntityManagerFactory` can be defined as shown in the following example:
-include-code::MyEntityManagerFactoryConfiguration[]
+include-code::MyAdditionalEntityManagerFactoryConfiguration[]
-The example above creates an `EntityManagerFactory` using a `DataSource` bean named `firstDataSource`.
+The example above creates an `EntityManagerFactory` using the `DataSource` bean qualified with `@Qualifier("second")`.
It scans entities located in the same package as `Order`.
-It is possible to map additional JPA properties using the `app.first.jpa` namespace.
+It is possible to map additional JPA properties using the `app.jpa` namespace.
+The use of `@Bean(defaultCandidate=false)` allows the `secondJpaProperties` and `secondEntityManagerFactory` beans to be defined without interfering with auto-configured beans of the same type.
-NOTE: When you create a bean for `LocalContainerEntityManagerFactoryBean` yourself, any customization that was applied during the creation of the auto-configured `LocalContainerEntityManagerFactoryBean` is lost.
-Make sure to use the auto-configured `EntityManagerFactoryBuilder` to retain JPA and vendor properties.
-This is particularly important if you were relying on `spring.jpa.*` properties for configuring things like the naming strategy or the DDL mode.
-
-You should provide a similar configuration for any additional data sources for which you need JPA access.
+You should provide a similar configuration for any more additional data sources for which you need JPA access.
To complete the picture, you need to configure a `JpaTransactionManager` for each `EntityManagerFactory` as well.
Alternatively, you might be able to use a JTA transaction manager that spans both.
diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.java
similarity index 59%
rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.java
rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.java
index c88ba5a727..7780541c17 100644
--- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.java
+++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2021 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -16,35 +16,20 @@
package org.springframework.boot.docs.howto.dataaccess.configuretwodatasources;
-import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
-public class MyDataSourcesConfiguration {
+public class MyAdditionalDataSourceConfiguration {
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first")
- public DataSourceProperties firstDataSourceProperties() {
- return new DataSourceProperties();
- }
-
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first.configuration")
- public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
- return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
- }
-
- @Bean
- @ConfigurationProperties("app.datasource.second")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource")
public BasicDataSource secondDataSource() {
return DataSourceBuilder.create().type(BasicDataSource.class).build();
}
diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.java
similarity index 64%
rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.java
rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.java
index f25837de72..829a9c413d 100644
--- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.java
+++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2021 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -16,7 +16,6 @@
package org.springframework.boot.docs.howto.dataaccess.configuretwodatasources;
-import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -24,33 +23,20 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
-public class MyCompleteDataSourcesConfiguration {
+public class MyCompleteAdditionalDataSourceConfiguration {
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first")
- public DataSourceProperties firstDataSourceProperties() {
- return new DataSourceProperties();
- }
-
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first.configuration")
- public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
- return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
- }
-
- @Bean
- @ConfigurationProperties("app.datasource.second")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
- @Bean
- @ConfigurationProperties("app.datasource.second.configuration")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource.configuration")
public BasicDataSource secondDataSource(
@Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource.class).build();
diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.java
similarity index 72%
rename from spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.java
rename to spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.java
index 11f898027b..8d26116a73 100644
--- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.java
+++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2021 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -18,6 +18,7 @@ package org.springframework.boot.docs.howto.dataaccess.usemultipleentitymanagers
import javax.sql.DataSource;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
@@ -28,19 +29,21 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
@Configuration(proxyBeanMethods = false)
-public class MyEntityManagerFactoryConfiguration {
+public class MyAdditionalEntityManagerFactoryConfiguration {
- @Bean
- @ConfigurationProperties("app.jpa.first")
- public JpaProperties firstJpaProperties() {
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.jpa")
+ public JpaProperties secondJpaProperties() {
return new JpaProperties();
}
- @Bean
- public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource firstDataSource,
- JpaProperties firstJpaProperties) {
- EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(firstJpaProperties);
- return builder.dataSource(firstDataSource).packages(Order.class).persistenceUnit("firstDs").build();
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(@Qualifier("second") DataSource dataSource,
+ @Qualifier("second") JpaProperties jpaProperties) {
+ EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(jpaProperties);
+ return builder.dataSource(dataSource).packages(Order.class).persistenceUnit("second").build();
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/Order.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/Order.java
index 333f4f615f..8f94cc06be 100644
--- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/Order.java
+++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/Order.java
@@ -16,6 +16,6 @@
package org.springframework.boot.docs.howto.dataaccess.usemultipleentitymanagers;
-class Order {
+public class Order {
}
diff --git a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/OrderConfiguration.java b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/OrderConfiguration.java
index 72f00ba0fb..7f86871cc4 100644
--- a/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/OrderConfiguration.java
+++ b/spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/OrderConfiguration.java
@@ -20,7 +20,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration(proxyBeanMethods = false)
-@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "firstEntityManagerFactory")
+@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "entityManagerFactory")
public class OrderConfiguration {
}
diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.kt
similarity index 59%
rename from spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.kt
rename to spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.kt
index 2e47fb8b10..401f08d7f4 100644
--- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfiguration.kt
+++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyAdditionalDataSourceConfiguration.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2022 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -16,34 +16,20 @@
package org.springframework.boot.docs.howto.dataaccess.configuretwodatasources
-import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
-import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
+
+import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.Primary
@Configuration(proxyBeanMethods = false)
-class MyDataSourcesConfiguration {
+class MyAdditionalDataSourceConfiguration {
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first")
- fun firstDataSourceProperties(): DataSourceProperties {
- return DataSourceProperties()
- }
-
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first.configuration")
- fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
- return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
- }
-
- @Bean
- @ConfigurationProperties("app.datasource.second")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource")
fun secondDataSource(): BasicDataSource {
return DataSourceBuilder.create().type(BasicDataSource::class.java).build()
}
diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.kt
similarity index 62%
rename from spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.kt
rename to spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.kt
index 24d142717a..cccbbff269 100644
--- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfiguration.kt
+++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteAdditionalDataSourceConfiguration.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2022 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -16,39 +16,27 @@
package org.springframework.boot.docs.howto.dataaccess.configuretwodatasources
-import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
+
+import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
-import org.springframework.context.annotation.Primary
@Configuration(proxyBeanMethods = false)
-class MyCompleteDataSourcesConfiguration {
+class MyCompleteAdditionalDataSourceConfiguration {
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first")
- fun firstDataSourceProperties(): DataSourceProperties {
- return DataSourceProperties()
- }
-
- @Bean
- @Primary
- @ConfigurationProperties("app.datasource.first.configuration")
- fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
- return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
- }
-
- @Bean
- @ConfigurationProperties("app.datasource.second")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource")
fun secondDataSourceProperties(): DataSourceProperties {
return DataSourceProperties()
}
- @Bean
- @ConfigurationProperties("app.datasource.second.configuration")
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.datasource.configuration")
fun secondDataSource(secondDataSourceProperties: DataSourceProperties): BasicDataSource {
return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource::class.java).build()
}
diff --git a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.kt b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.kt
similarity index 76%
rename from spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.kt
rename to spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.kt
index ef844b3ab3..55eefdd7e5 100644
--- a/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyEntityManagerFactoryConfiguration.kt
+++ b/spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/howto/dataaccess/usemultipleentitymanagers/MyAdditionalEntityManagerFactoryConfiguration.kt
@@ -18,6 +18,7 @@ package org.springframework.boot.docs.howto.dataaccess.usemultipleentitymanagers
import javax.sql.DataSource
+import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
@@ -29,21 +30,23 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
@Suppress("UNUSED_PARAMETER")
@Configuration(proxyBeanMethods = false)
-class MyEntityManagerFactoryConfiguration {
+class MyAdditionalEntityManagerFactoryConfiguration {
- @Bean
- @ConfigurationProperties("app.jpa.first")
- fun firstJpaProperties(): JpaProperties {
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
+ @ConfigurationProperties("app.jpa")
+ fun secondJpaProperties(): JpaProperties {
return JpaProperties()
}
- @Bean
+ @Qualifier("second")
+ @Bean(defaultCandidate = false)
fun firstEntityManagerFactory(
- firstDataSource: DataSource?,
- firstJpaProperties: JpaProperties
+ @Qualifier("second") dataSource: DataSource,
+ @Qualifier("second") jpaProperties: JpaProperties
): LocalContainerEntityManagerFactoryBean {
- val builder = createEntityManagerFactoryBuilder(firstJpaProperties)
- return builder.dataSource(firstDataSource).packages(Order::class.java).persistenceUnit("firstDs").build()
+ val builder = createEntityManagerFactoryBuilder(jpaProperties)
+ return builder.dataSource(dataSource).packages(Order::class.java).persistenceUnit("second").build()
}
private fun createEntityManagerFactoryBuilder(jpaProperties: JpaProperties): EntityManagerFactoryBuilder {
diff --git a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfigurationTests.java b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfigurationTests.java
index aa3be89a0c..143ab49855 100644
--- a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfigurationTests.java
+++ b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyCompleteDataSourcesConfigurationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2021 the original author or authors.
+ * Copyright 2012-2024 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.
@@ -21,37 +21,41 @@ import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link MyCompleteDataSourcesConfiguration}.
+ * Tests for {@link MyCompleteAdditionalDataSourceConfiguration}.
*
* @author Stephane Nicoll
*/
-@ExtendWith(SpringExtension.class)
@SpringBootTest
-@Import(MyCompleteDataSourcesConfiguration.class)
+@Import(MyCompleteAdditionalDataSourceConfiguration.class)
class MyCompleteDataSourcesConfigurationTests {
@Autowired
private ApplicationContext context;
+ @Autowired
+ private DataSource dataSource;
+
+ @Autowired
+ @Qualifier("second")
+ private DataSource secondDataSource;
+
@Test
void validateConfiguration() throws SQLException {
assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(2);
- DataSource dataSource = this.context.getBean(DataSource.class);
- assertThat(this.context.getBean("firstDataSource")).isSameAs(dataSource);
- assertThat(dataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
- DataSource secondDataSource = this.context.getBean("secondDataSource", DataSource.class);
- assertThat(secondDataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
+ assertThat(this.context.getBean("dataSource")).isSameAs(this.dataSource);
+ assertThat(this.dataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
+ assertThat(this.context.getBean("secondDataSource")).isSameAs(this.secondDataSource);
+ assertThat(this.secondDataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
}
}
diff --git a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfigurationTests.java b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfigurationTests.java
index 6034bae765..cd0308777a 100644
--- a/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfigurationTests.java
+++ b/spring-boot-project/spring-boot-docs/src/test/java/org/springframework/boot/docs/howto/dataaccess/configuretwodatasources/MyDataSourcesConfigurationTests.java
@@ -22,39 +22,44 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests for {@link MyDataSourcesConfiguration}.
+ * Tests for {@link MyAdditionalDataSourceConfiguration}.
*
* @author Stephane Nicoll
*/
-@ExtendWith(SpringExtension.class)
-@SpringBootTest(properties = { "app.datasource.second.url=jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1",
- "app.datasource.second.max-total=42" })
-@Import(MyDataSourcesConfiguration.class)
+@SpringBootTest(properties = { "app.datasource.url=jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1", "app.datasource.max-total=42" })
+@Import(MyAdditionalDataSourceConfiguration.class)
class MyDataSourcesConfigurationTests {
@Autowired
private ApplicationContext context;
+ @Autowired
+ private DataSource dataSource;
+
+ @Autowired
+ @Qualifier("second")
+ private DataSource secondDataSource;
+
@Test
void validateConfiguration() throws SQLException {
assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(2);
- DataSource dataSource = this.context.getBean(DataSource.class);
- assertThat(this.context.getBean("firstDataSource")).isSameAs(dataSource);
- assertThat(dataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
- BasicDataSource secondDataSource = this.context.getBean("secondDataSource", BasicDataSource.class);
- assertThat(secondDataSource.getUrl()).isEqualTo("jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1");
- assertThat(secondDataSource.getMaxTotal()).isEqualTo(42);
+ assertThat(this.context.getBean("dataSource")).isSameAs(this.dataSource);
+ assertThat(this.dataSource.getConnection().getMetaData().getURL()).startsWith("jdbc:h2:mem:");
+ assertThat(this.context.getBean("secondDataSource")).isSameAs(this.secondDataSource);
+ assertThat(this.secondDataSource).extracting((dataSource) -> ((BasicDataSource) dataSource).getUrl())
+ .isEqualTo("jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1");
+ assertThat(this.secondDataSource).extracting((dataSource) -> ((BasicDataSource) dataSource).getMaxTotal())
+ .isEqualTo(42);
}
}