Skip to content

Commit 1a486fb

Browse files
committed
Add auto-configuration for JdbcClient
Closes spring-projectsgh-36579
1 parent b37d70b commit 1a486fb

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2023 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+
* https://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 org.springframework.boot.autoconfigure.AutoConfiguration;
20+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
25+
import org.springframework.jdbc.core.simple.JdbcClient;
26+
27+
/**
28+
* {@link EnableAutoConfiguration Auto-configuration} for {@link JdbcClient}.
29+
*
30+
* @author Stephane Nicoll
31+
* @since 3.2.0
32+
*/
33+
@AutoConfiguration(after = JdbcTemplateAutoConfiguration.class)
34+
@ConditionalOnSingleCandidate(NamedParameterJdbcTemplate.class)
35+
@ConditionalOnMissingBean(JdbcClient.class)
36+
public class JdbcClientAutoConfiguration {
37+
38+
@Bean
39+
JdbcClient jdbcClient(NamedParameterJdbcTemplate jdbcTemplate) {
40+
return JdbcClient.create(jdbcTemplate);
41+
}
42+
43+
}

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
6868
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration
6969
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
7070
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
71+
org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration
7172
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
7273
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
7374
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2012-2023 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+
* https://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 org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.autoconfigure.AutoConfigurations;
22+
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
23+
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
24+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
25+
import org.springframework.jdbc.core.JdbcOperations;
26+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
27+
import org.springframework.jdbc.core.simple.JdbcClient;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.mockito.Mockito.mock;
31+
32+
/**
33+
* Tests for {@link JdbcClientAutoConfiguration}.
34+
*
35+
* @author Stephane Nicoll
36+
*/
37+
class JdbcClientAutoConfigurationTests {
38+
39+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
40+
.withPropertyValues("spring.datasource.generate-unique-name=true")
41+
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
42+
JdbcClientAutoConfiguration.class));
43+
44+
@Test
45+
void jdbcClientWhenNoAvailableJdbcTemplateIsNotCreated() {
46+
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
47+
.run((context) -> assertThat(context).doesNotHaveBean(JdbcClient.class));
48+
}
49+
50+
@Test
51+
void jdbcClientWhenExistingJdbcTemplateIsCreated() {
52+
this.contextRunner.run((context) -> {
53+
assertThat(context).hasSingleBean(JdbcClient.class);
54+
NamedParameterJdbcTemplate namedParameterJdbcTemplate = context.getBean(NamedParameterJdbcTemplate.class);
55+
assertThat(namedParameterJdbcTemplate.getJdbcOperations()).isEqualTo(context.getBean(JdbcOperations.class));
56+
});
57+
}
58+
59+
@Test
60+
void jdbcClientWithCustomJdbcClientIsNotCreated() {
61+
this.contextRunner.withBean("customJdbcClient", JdbcClient.class, () -> mock(JdbcClient.class))
62+
.run((context) -> {
63+
assertThat(context).hasSingleBean(JdbcClient.class);
64+
assertThat(context.getBean(JdbcClient.class)).isEqualTo(context.getBean("customJdbcClient"));
65+
});
66+
}
67+
68+
@Test
69+
void jdbcClientIsOrderedAfterFlywayMigration() {
70+
this.contextRunner.withUserConfiguration(JdbcClientDataSourceMigrationValidator.class)
71+
.withPropertyValues("spring.flyway.locations:classpath:db/city")
72+
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
73+
.run((context) -> {
74+
assertThat(context).hasNotFailed().hasSingleBean(JdbcClient.class);
75+
assertThat(context.getBean(JdbcClientDataSourceMigrationValidator.class).count).isZero();
76+
});
77+
}
78+
79+
@Test
80+
void jdbcClientIsOrderedAfterLiquibaseMigration() {
81+
this.contextRunner.withUserConfiguration(JdbcClientDataSourceMigrationValidator.class)
82+
.withPropertyValues("spring.liquibase.changeLog:classpath:db/changelog/db.changelog-city.yaml")
83+
.withConfiguration(AutoConfigurations.of(LiquibaseAutoConfiguration.class))
84+
.run((context) -> {
85+
assertThat(context).hasNotFailed().hasSingleBean(JdbcClient.class);
86+
assertThat(context.getBean(JdbcClientDataSourceMigrationValidator.class).count).isZero();
87+
});
88+
}
89+
90+
static class JdbcClientDataSourceMigrationValidator {
91+
92+
private final Integer count;
93+
94+
JdbcClientDataSourceMigrationValidator(JdbcClient jdbcClient) {
95+
this.count = jdbcClient.sql("SELECT COUNT(*) from CITY").query().singleValue(Integer.class);
96+
}
97+
98+
}
99+
100+
}

0 commit comments

Comments
 (0)