Skip to content

Commit 5ecb68b

Browse files
kazuki43zoophilwebb
authored andcommitted
Add JdbcTemplate only on single DataSource
Update auto-configuration logic so that a `JdbcTemplate` is only added when there is a single candidate DataSource bean. Closes gh-6449
1 parent e0adacb commit 5ecb68b

File tree

6 files changed

+235
-61
lines changed

6 files changed

+235
-61
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@
4747
import org.springframework.core.Ordered;
4848
import org.springframework.core.annotation.Order;
4949
import org.springframework.core.type.AnnotatedTypeMetadata;
50-
import org.springframework.jdbc.core.JdbcOperations;
51-
import org.springframework.jdbc.core.JdbcTemplate;
52-
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
53-
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
5450
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
5551

5652
/**
@@ -108,29 +104,6 @@ protected static class PooledDataSourceConfiguration {
108104

109105
}
110106

111-
@Configuration
112-
@Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
113-
protected static class JdbcTemplateConfiguration {
114-
115-
private final DataSource dataSource;
116-
117-
public JdbcTemplateConfiguration(DataSource dataSource) {
118-
this.dataSource = dataSource;
119-
}
120-
121-
@Bean
122-
@ConditionalOnMissingBean(JdbcOperations.class)
123-
public JdbcTemplate jdbcTemplate() {
124-
return new JdbcTemplate(this.dataSource);
125-
}
126-
127-
@Bean
128-
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
129-
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
130-
return new NamedParameterJdbcTemplate(this.dataSource);
131-
}
132-
}
133-
134107
@Configuration
135108
@ConditionalOnProperty(prefix = "spring.datasource", name = "jmx-enabled")
136109
@ConditionalOnClass(name = "org.apache.tomcat.jdbc.pool.DataSourceProxy")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2012-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jdbc;
18+
19+
import javax.sql.DataSource;
20+
21+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
22+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.jdbc.core.JdbcOperations;
29+
import org.springframework.jdbc.core.JdbcTemplate;
30+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
31+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
32+
33+
/**
34+
* {@link EnableAutoConfiguration Auto-configuration} for {@link JdbcTemplate} and
35+
* {@link NamedParameterJdbcTemplate}.
36+
*
37+
* @author Dave Syer
38+
* @author Phillip Webb
39+
* @author Stephane Nicoll
40+
* @author Kazuki Shimizu
41+
* @since 1.4.0
42+
*/
43+
@Configuration
44+
@ConditionalOnClass(DataSource.class)
45+
@ConditionalOnSingleCandidate(DataSource.class)
46+
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
47+
public class JdbcTemplateAutoConfiguration {
48+
49+
private final DataSource dataSource;
50+
51+
public JdbcTemplateAutoConfiguration(DataSource dataSource) {
52+
this.dataSource = dataSource;
53+
}
54+
55+
@Bean
56+
@ConditionalOnMissingBean(JdbcOperations.class)
57+
public JdbcTemplate jdbcTemplate() {
58+
return new JdbcTemplate(this.dataSource);
59+
}
60+
61+
@Bean
62+
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
63+
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
64+
return new NamedParameterJdbcTemplate(this.dataSource);
65+
}
66+
67+
}

spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
4949
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
5050
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
5151
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
52+
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
5253
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
5354
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
5455
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4343
import org.springframework.context.annotation.Bean;
4444
import org.springframework.context.annotation.Configuration;
45-
import org.springframework.jdbc.core.JdbcTemplate;
46-
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
4745

4846
import static org.assertj.core.api.Assertions.assertThat;
4947
import static org.mockito.Mockito.mock;
@@ -228,35 +226,6 @@ public void testDefaultDataSourceCanBeOverridden() throws Exception {
228226
assertThat(dataSource).isInstanceOf(BasicDataSource.class);
229227
}
230228

231-
@Test
232-
public void testJdbcTemplateExists() throws Exception {
233-
this.context.register(DataSourceAutoConfiguration.class,
234-
PropertyPlaceholderAutoConfiguration.class);
235-
this.context.refresh();
236-
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
237-
assertThat(jdbcTemplate).isNotNull();
238-
assertThat(jdbcTemplate.getDataSource()).isNotNull();
239-
}
240-
241-
@Test
242-
public void testJdbcTemplateExistsWithCustomDataSource() throws Exception {
243-
this.context.register(TestDataSourceConfiguration.class,
244-
DataSourceAutoConfiguration.class,
245-
PropertyPlaceholderAutoConfiguration.class);
246-
this.context.refresh();
247-
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
248-
assertThat(jdbcTemplate).isNotNull();
249-
assertThat(jdbcTemplate.getDataSource() instanceof BasicDataSource).isTrue();
250-
}
251-
252-
@Test
253-
public void testNamedParameterJdbcTemplateExists() throws Exception {
254-
this.context.register(DataSourceAutoConfiguration.class,
255-
PropertyPlaceholderAutoConfiguration.class);
256-
this.context.refresh();
257-
assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull();
258-
}
259-
260229
@SuppressWarnings("unchecked")
261230
private <T extends DataSource> T autoConfigureDataSource(Class<T> expectedType,
262231
final String... hiddenPackages) {

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializerTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.junit.Before;
2929
import org.junit.Test;
3030

31-
import org.springframework.beans.factory.UnsatisfiedDependencyException;
31+
import org.springframework.beans.factory.BeanCreationException;
3232
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
3333
import org.springframework.boot.context.properties.ConfigurationProperties;
3434
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -223,7 +223,7 @@ public void testDataSourceInitializedWithSchemaCredentials() {
223223
fail("User does not exist");
224224
}
225225
catch (Exception ex) {
226-
assertThat(ex).isInstanceOf(UnsatisfiedDependencyException.class);
226+
assertThat(ex).isInstanceOf(BeanCreationException.class);
227227
}
228228
}
229229

@@ -245,7 +245,7 @@ public void testDataSourceInitializedWithDataCredentials() {
245245
fail("User does not exist");
246246
}
247247
catch (Exception ex) {
248-
assertThat(ex).isInstanceOf(UnsatisfiedDependencyException.class);
248+
assertThat(ex).isInstanceOf(BeanCreationException.class);
249249
}
250250
}
251251

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright 2012-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jdbc;
18+
19+
import java.util.Random;
20+
21+
import javax.sql.DataSource;
22+
23+
import org.apache.commons.dbcp.BasicDataSource;
24+
import org.junit.After;
25+
import org.junit.Before;
26+
import org.junit.Test;
27+
28+
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
29+
import org.springframework.boot.test.util.EnvironmentTestUtils;
30+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.jdbc.core.JdbcOperations;
34+
import org.springframework.jdbc.core.JdbcTemplate;
35+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
36+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
37+
38+
import static org.assertj.core.api.Assertions.assertThat;
39+
40+
/**
41+
* Tests for {@link DataSourceAutoConfiguration}.
42+
*
43+
* @author Dave Syer
44+
* @author Stephane Nicoll
45+
* @author Kazuki Shimizu
46+
* @since 1.4.0
47+
*/
48+
public class JdbcTemplateAutoConfigurationTests {
49+
50+
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
51+
52+
@Before
53+
public void init() {
54+
EmbeddedDatabaseConnection.override = null;
55+
EnvironmentTestUtils.addEnvironment(this.context,
56+
"spring.datasource.initialize:false",
57+
"spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt());
58+
}
59+
60+
@After
61+
public void restore() {
62+
EmbeddedDatabaseConnection.override = null;
63+
this.context.close();
64+
}
65+
66+
@Test
67+
public void testJdbcTemplateExists() throws Exception {
68+
this.context.register(DataSourceAutoConfiguration.class,
69+
JdbcTemplateAutoConfiguration.class,
70+
PropertyPlaceholderAutoConfiguration.class);
71+
this.context.refresh();
72+
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
73+
assertThat(jdbcTemplate).isNotNull();
74+
assertThat(jdbcTemplate.getDataSource()).isNotNull();
75+
}
76+
77+
@Test
78+
public void testJdbcTemplateExistsWithCustomDataSource() throws Exception {
79+
this.context.register(TestDataSourceConfiguration.class,
80+
DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
81+
PropertyPlaceholderAutoConfiguration.class);
82+
this.context.refresh();
83+
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
84+
assertThat(jdbcTemplate).isNotNull();
85+
assertThat(jdbcTemplate.getDataSource() instanceof BasicDataSource).isTrue();
86+
}
87+
88+
@Test
89+
public void testNamedParameterJdbcTemplateExists() throws Exception {
90+
this.context.register(DataSourceAutoConfiguration.class,
91+
JdbcTemplateAutoConfiguration.class,
92+
PropertyPlaceholderAutoConfiguration.class);
93+
this.context.refresh();
94+
assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull();
95+
}
96+
97+
@Test
98+
public void testMultiDataSource() throws Exception {
99+
this.context.register(MultiDataSourceConfiguration.class,
100+
DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
101+
PropertyPlaceholderAutoConfiguration.class);
102+
this.context.refresh();
103+
assertThat(this.context.getBeansOfType(JdbcOperations.class)).isEmpty();
104+
assertThat(this.context.getBeansOfType(NamedParameterJdbcOperations.class))
105+
.isEmpty();
106+
}
107+
108+
@Test
109+
public void testMultiDataSourceUsingPrimary() throws Exception {
110+
this.context.register(MultiDataSourceUsingPrimaryConfiguration.class,
111+
DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
112+
PropertyPlaceholderAutoConfiguration.class);
113+
this.context.refresh();
114+
assertThat(this.context.getBean(JdbcOperations.class)).isNotNull();
115+
assertThat(this.context.getBean(NamedParameterJdbcOperations.class)).isNotNull();
116+
}
117+
118+
@Test
119+
public void testExistingCustomJdbcTemplate() throws Exception {
120+
this.context.register(CustomConfiguration.class,
121+
DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
122+
PropertyPlaceholderAutoConfiguration.class);
123+
this.context.refresh();
124+
assertThat(this.context.getBean(JdbcOperations.class))
125+
.isEqualTo(this.context.getBean("customJdbcOperations"));
126+
}
127+
128+
@Test
129+
public void testExistingCustomNamedParameterJdbcTemplate() throws Exception {
130+
this.context.register(CustomConfiguration.class,
131+
DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
132+
PropertyPlaceholderAutoConfiguration.class);
133+
this.context.refresh();
134+
assertThat(this.context.getBean(NamedParameterJdbcOperations.class))
135+
.isEqualTo(this.context.getBean("customNamedParameterJdbcOperations"));
136+
}
137+
138+
@Configuration
139+
static class CustomConfiguration {
140+
141+
@Bean
142+
public JdbcOperations customJdbcOperations(DataSource dataSource) {
143+
return new JdbcTemplate(dataSource);
144+
}
145+
146+
@Bean
147+
public NamedParameterJdbcOperations customNamedParameterJdbcOperations(
148+
DataSource dataSource) {
149+
return new NamedParameterJdbcTemplate(dataSource);
150+
}
151+
152+
}
153+
154+
@Configuration
155+
static class TestDataSourceConfiguration {
156+
157+
@Bean
158+
public DataSource dataSource() {
159+
return new TestDataSource("overridedb");
160+
}
161+
162+
}
163+
164+
}

0 commit comments

Comments
 (0)