Skip to content

Commit 7c3576b

Browse files
committed
Polish "Add ProxyConnectionFactoryCustomizer"
See gh-40555
1 parent 75ae7c9 commit 7c3576b

File tree

8 files changed

+159
-75
lines changed

8 files changed

+159
-75
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/r2dbc/R2dbcObservationAutoConfiguration.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@
3030
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3131
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3232
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
33+
import org.springframework.boot.autoconfigure.r2dbc.ProxyConnectionFactoryCustomizer;
3334
import org.springframework.boot.context.properties.EnableConfigurationProperties;
34-
import org.springframework.boot.r2dbc.ConnectionFactoryDecorator;
3535
import org.springframework.boot.r2dbc.OptionsCapableConnectionFactory;
36-
import org.springframework.boot.r2dbc.ProxyConnectionFactoryCustomizer;
3736
import org.springframework.context.annotation.Bean;
3837
import org.springframework.core.annotation.Order;
3938

@@ -50,24 +49,14 @@
5049
public class R2dbcObservationAutoConfiguration {
5150

5251
/**
53-
* {@code @Order} value of observation customizer.
52+
* {@code @Order} value of the observation customizer.
5453
*/
55-
public static final int R2DBC_PROXY_OBSERVATION_CUSTOMIZER_ORDER = 1000;
56-
57-
@Bean
58-
ConnectionFactoryDecorator connectionFactoryDecorator(
59-
ObjectProvider<ProxyConnectionFactoryCustomizer> customizers) {
60-
return (connectionFactory) -> {
61-
ProxyConnectionFactory.Builder builder = ProxyConnectionFactory.builder(connectionFactory);
62-
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
63-
return builder.build();
64-
};
65-
}
54+
public static final int R2DBC_PROXY_OBSERVATION_CUSTOMIZER_ORDER = 0;
6655

6756
@Bean
6857
@Order(R2DBC_PROXY_OBSERVATION_CUSTOMIZER_ORDER)
6958
@ConditionalOnBean(ObservationRegistry.class)
70-
ProxyConnectionFactoryCustomizer proxyConnectionFactoryObservationCustomizer(R2dbcObservationProperties properties,
59+
ProxyConnectionFactoryCustomizer observationProxyConnectionFactoryCustomizer(R2dbcObservationProperties properties,
7160
ObservationRegistry observationRegistry,
7261
ObjectProvider<QueryObservationConvention> queryObservationConvention,
7362
ObjectProvider<QueryParametersTagProvider> queryParametersTagProvider) {

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/r2dbc/R2dbcObservationAutoConfigurationTests.java

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.r2dbc;
1818

19-
import java.util.ArrayList;
20-
import java.util.List;
2119
import java.util.UUID;
2220
import java.util.concurrent.atomic.AtomicReference;
2321

@@ -27,21 +25,18 @@
2725
import io.r2dbc.spi.ConnectionFactory;
2826
import org.awaitility.Awaitility;
2927
import org.hamcrest.Matchers;
30-
import org.junit.jupiter.api.Order;
3128
import org.junit.jupiter.api.Test;
3229
import reactor.core.publisher.Mono;
3330

3431
import org.springframework.boot.autoconfigure.AutoConfiguration;
3532
import org.springframework.boot.autoconfigure.AutoConfigurations;
33+
import org.springframework.boot.autoconfigure.r2dbc.ProxyConnectionFactoryCustomizer;
34+
import org.springframework.boot.autoconfigure.r2dbc.R2dbcProxyAutoConfiguration;
3635
import org.springframework.boot.context.annotation.ImportCandidates;
3736
import org.springframework.boot.r2dbc.ConnectionFactoryBuilder;
3837
import org.springframework.boot.r2dbc.ConnectionFactoryDecorator;
39-
import org.springframework.boot.r2dbc.ProxyConnectionFactoryCustomizer;
40-
import org.springframework.boot.test.context.FilteredClassLoader;
4138
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
4239
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
43-
import org.springframework.context.annotation.Bean;
44-
import org.springframework.context.annotation.Configuration;
4540

4641
import static org.assertj.core.api.Assertions.assertThat;
4742

@@ -54,7 +49,8 @@
5449
class R2dbcObservationAutoConfigurationTests {
5550

5651
private final ApplicationContextRunner runnerWithoutObservationRegistry = new ApplicationContextRunner()
57-
.withConfiguration(AutoConfigurations.of(R2dbcObservationAutoConfiguration.class));
52+
.withConfiguration(
53+
AutoConfigurations.of(R2dbcProxyAutoConfiguration.class, R2dbcObservationAutoConfiguration.class));
5854

5955
private final ApplicationContextRunner runner = this.runnerWithoutObservationRegistry
6056
.withBean(ObservationRegistry.class, ObservationRegistry::create);
@@ -65,42 +61,12 @@ void shouldBeRegisteredInAutoConfigurationImports() {
6561
.contains(R2dbcObservationAutoConfiguration.class.getName());
6662
}
6763

68-
@Test
69-
void shouldSupplyConnectionFactoryDecorator() {
70-
this.runner.run((context) -> assertThat(context).hasSingleBean(ConnectionFactoryDecorator.class));
71-
}
72-
73-
@Test
74-
void shouldNotSupplyBeansIfR2dbcSpiIsNotOnClasspath() {
75-
this.runner.withClassLoader(new FilteredClassLoader("io.r2dbc.spi"))
76-
.run((context) -> assertThat(context).doesNotHaveBean(ConnectionFactoryDecorator.class));
77-
}
78-
79-
@Test
80-
void shouldNotSupplyBeansIfR2dbcProxyIsNotOnClasspath() {
81-
this.runner.withClassLoader(new FilteredClassLoader("io.r2dbc.proxy"))
82-
.run((context) -> assertThat(context).doesNotHaveBean(ConnectionFactoryDecorator.class));
83-
}
84-
8564
@Test
8665
void shouldNotSupplyBeansIfObservationRegistryIsNotPresent() {
8766
this.runnerWithoutObservationRegistry
8867
.run((context) -> assertThat(context).doesNotHaveBean(ProxyConnectionFactoryCustomizer.class));
8968
}
9069

91-
@Test
92-
void shouldApplyCustomizers() {
93-
this.runner.withUserConfiguration(ProxyConnectionFactoryCustomizerConfig.class).run((context) -> {
94-
ConnectionFactoryDecorator decorator = context.getBean(ConnectionFactoryDecorator.class);
95-
ConnectionFactory connectionFactory = ConnectionFactoryBuilder
96-
.withUrl("r2dbc:h2:mem:///" + UUID.randomUUID())
97-
.build();
98-
decorator.decorate(connectionFactory);
99-
assertThat(context.getBean(ProxyConnectionFactoryCustomizerConfig.class).called).containsExactly("first",
100-
"second");
101-
});
102-
}
103-
10470
@Test
10571
void decoratorShouldReportObservations() {
10672
this.runner.run((context) -> {
@@ -148,23 +114,4 @@ Context awaitContext() {
148114

149115
}
150116

151-
@Configuration(proxyBeanMethods = false)
152-
private static final class ProxyConnectionFactoryCustomizerConfig {
153-
154-
private final List<String> called = new ArrayList<>();
155-
156-
@Bean
157-
@Order(R2dbcObservationAutoConfiguration.R2DBC_PROXY_OBSERVATION_CUSTOMIZER_ORDER - 1)
158-
ProxyConnectionFactoryCustomizer first() {
159-
return (builder) -> this.called.add("first");
160-
}
161-
162-
@Bean
163-
@Order(R2dbcObservationAutoConfiguration.R2DBC_PROXY_OBSERVATION_CUSTOMIZER_ORDER + 1)
164-
ProxyConnectionFactoryCustomizer second() {
165-
return (builder) -> this.called.add("second");
166-
}
167-
168-
}
169-
170117
}

spring-boot-project/spring-boot-autoconfigure/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ dependencies {
5050
optional("io.projectreactor.netty:reactor-netty-http")
5151
optional("io.r2dbc:r2dbc-spi")
5252
optional("io.r2dbc:r2dbc-pool")
53+
optional("io.r2dbc:r2dbc-proxy")
5354
optional("io.rsocket:rsocket-core")
5455
optional("io.rsocket:rsocket-transport-netty")
5556
optional("io.undertow:undertow-servlet")

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/ProxyConnectionFactoryCustomizer.java renamed to spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ProxyConnectionFactoryCustomizer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot.r2dbc;
17+
package org.springframework.boot.autoconfigure.r2dbc;
1818

1919
import io.r2dbc.proxy.ProxyConnectionFactory;
2020

@@ -23,7 +23,7 @@
2323
* {@link ProxyConnectionFactory.Builder}.
2424
*
2525
* @author Tadaya Tsuyukubo
26-
* @since 3.3
26+
* @since 3.4.0
2727
*/
2828
public interface ProxyConnectionFactoryCustomizer {
2929

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2012-2024 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.r2dbc;
18+
19+
import io.r2dbc.proxy.ProxyConnectionFactory;
20+
import io.r2dbc.spi.ConnectionFactory;
21+
22+
import org.springframework.beans.factory.ObjectProvider;
23+
import org.springframework.boot.autoconfigure.AutoConfiguration;
24+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
26+
import org.springframework.boot.r2dbc.ConnectionFactoryDecorator;
27+
import org.springframework.context.annotation.Bean;
28+
29+
/**
30+
* {@link EnableAutoConfiguration Auto-configuration} for {@link ProxyConnectionFactory}.
31+
*
32+
* @author Tadaya Tsuyukubo
33+
* @author Moritz Halbritter
34+
* @since 3.4.0
35+
*/
36+
@AutoConfiguration
37+
@ConditionalOnClass({ ConnectionFactory.class, ProxyConnectionFactory.class })
38+
public class R2dbcProxyAutoConfiguration {
39+
40+
@Bean
41+
ConnectionFactoryDecorator connectionFactoryDecorator(
42+
ObjectProvider<ProxyConnectionFactoryCustomizer> customizers) {
43+
return (connectionFactory) -> {
44+
ProxyConnectionFactory.Builder builder = ProxyConnectionFactory.builder(connectionFactory);
45+
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
46+
return builder.build();
47+
};
48+
}
49+
50+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ org.springframework.boot.autoconfigure.pulsar.PulsarAutoConfiguration
9898
org.springframework.boot.autoconfigure.pulsar.PulsarReactiveAutoConfiguration
9999
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration
100100
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration
101+
org.springframework.boot.autoconfigure.r2dbc.R2dbcProxyAutoConfiguration
101102
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration
102103
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration
103104
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2012-2024 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.r2dbc;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.UUID;
22+
23+
import io.r2dbc.spi.ConnectionFactory;
24+
import org.junit.jupiter.api.Test;
25+
26+
import org.springframework.boot.autoconfigure.AutoConfigurations;
27+
import org.springframework.boot.r2dbc.ConnectionFactoryBuilder;
28+
import org.springframework.boot.r2dbc.ConnectionFactoryDecorator;
29+
import org.springframework.boot.test.context.FilteredClassLoader;
30+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.core.annotation.Order;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* Tests for {@link R2dbcProxyAutoConfiguration}.
39+
*
40+
* @author Tadaya Tsuyukubo
41+
* @author Moritz Halbritter
42+
*/
43+
class R2dbcProxyAutoConfigurationTests {
44+
45+
private final ApplicationContextRunner runner = new ApplicationContextRunner()
46+
.withConfiguration(AutoConfigurations.of(R2dbcProxyAutoConfiguration.class));
47+
48+
@Test
49+
void shouldSupplyConnectionFactoryDecorator() {
50+
this.runner.run((context) -> assertThat(context).hasSingleBean(ConnectionFactoryDecorator.class));
51+
}
52+
53+
@Test
54+
void shouldNotSupplyBeansIfR2dbcSpiIsNotOnClasspath() {
55+
this.runner.withClassLoader(new FilteredClassLoader("io.r2dbc.spi"))
56+
.run((context) -> assertThat(context).doesNotHaveBean(ConnectionFactoryDecorator.class));
57+
}
58+
59+
@Test
60+
void shouldNotSupplyBeansIfR2dbcProxyIsNotOnClasspath() {
61+
this.runner.withClassLoader(new FilteredClassLoader("io.r2dbc.proxy"))
62+
.run((context) -> assertThat(context).doesNotHaveBean(ConnectionFactoryDecorator.class));
63+
}
64+
65+
@Test
66+
void shouldApplyCustomizers() {
67+
this.runner.withUserConfiguration(ProxyConnectionFactoryCustomizerConfig.class).run((context) -> {
68+
ConnectionFactoryDecorator decorator = context.getBean(ConnectionFactoryDecorator.class);
69+
ConnectionFactory connectionFactory = ConnectionFactoryBuilder
70+
.withUrl("r2dbc:h2:mem:///" + UUID.randomUUID())
71+
.build();
72+
decorator.decorate(connectionFactory);
73+
assertThat(context.getBean(ProxyConnectionFactoryCustomizerConfig.class).called).containsExactly("first",
74+
"second");
75+
});
76+
}
77+
78+
@Configuration(proxyBeanMethods = false)
79+
private static final class ProxyConnectionFactoryCustomizerConfig {
80+
81+
private final List<String> called = new ArrayList<>();
82+
83+
@Bean
84+
@Order(1)
85+
ProxyConnectionFactoryCustomizer first() {
86+
return (builder) -> this.called.add("first");
87+
}
88+
89+
@Bean
90+
@Order(2)
91+
ProxyConnectionFactoryCustomizer second() {
92+
return (builder) -> this.called.add("second");
93+
}
94+
95+
}
96+
97+
}

spring-boot-project/spring-boot/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ dependencies {
3535
optional("io.projectreactor:reactor-tools")
3636
optional("io.projectreactor.netty:reactor-netty-http")
3737
optional("io.r2dbc:r2dbc-pool")
38-
optional("io.r2dbc:r2dbc-proxy")
3938
optional("io.rsocket:rsocket-core")
4039
optional("io.rsocket:rsocket-transport-netty")
4140
optional("io.undertow:undertow-servlet")

0 commit comments

Comments
 (0)