From eeb961075f78caf8180667cff797454f814dbe5b Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 29 May 2017 10:25:34 +0200 Subject: [PATCH 1/2] Allow customization of MongoClientSettings.Builder MongoClientSettingsBuilderCustomizer allows customization of the auto-configured `MongoClientSettings.Builder`. See gh-9341 --- .../MongoClientSettingsBuilderCustomizer.java | 38 ++++++++++++ .../mongo/MongoReactiveAutoConfiguration.java | 8 ++- .../mongo/ReactiveMongoClientFactory.java | 16 ++++- .../MongoReactiveAutoConfigurationTests.java | 58 +++++++++++++++++++ .../ReactiveMongoClientFactoryTests.java | 2 +- 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java new file mode 100644 index 00000000000..77f8a03085f --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2017 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 + * + * http://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.mongo; + +import com.mongodb.async.client.MongoClientSettings.Builder; + +/** + * Callback interface that can be implemented by beans wishing to customize the + * {@link com.mongodb.async.client.MongoClientSettings} via a {@link Builder + * MongoClientSettings.Builder} whilst retaining default auto-configuration. + * + * @author Mark Paluch + * @since 2.0.0 + */ +@FunctionalInterface +public interface MongoClientSettingsBuilderCustomizer { + + /** + * Customize the {@link Builder}. + * @param settingsBuilder the builder to customize + */ + void customize(Builder settingsBuilder); + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java index bbcd0c1f32d..b04c1a895ec 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.mongo; +import java.util.List; + import javax.annotation.PreDestroy; import com.mongodb.async.client.MongoClientSettings; @@ -49,9 +51,11 @@ public class MongoReactiveAutoConfiguration { private MongoClient mongo; public MongoReactiveAutoConfiguration(MongoProperties properties, - ObjectProvider settings, Environment environment) { + ObjectProvider settings, Environment environment, + ObjectProvider> builderCustomizers) { this.settings = settings.getIfAvailable(); - this.factory = new ReactiveMongoClientFactory(properties, environment); + this.factory = new ReactiveMongoClientFactory(properties, environment, + builderCustomizers.getIfAvailable()); } @PreDestroy diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java index b9294403783..0d4335702f3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java @@ -48,10 +48,13 @@ public class ReactiveMongoClientFactory { private final Environment environment; - public ReactiveMongoClientFactory(MongoProperties properties, - Environment environment) { + private final List builderCustomizers; + + public ReactiveMongoClientFactory(MongoProperties properties, Environment environment, + List builderCustomizers) { this.properties = properties; this.environment = environment; + this.builderCustomizers = builderCustomizers; } /** @@ -149,9 +152,18 @@ public class ReactiveMongoClientFactory { if (connectionString.getApplicationName() != null) { builder.applicationName(connectionString.getApplicationName()); } + customize(builder); return builder; } + private void customize(MongoClientSettings.Builder builder) { + if (this.builderCustomizers != null) { + for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) { + customizer.customize(builder); + } + } + } + private boolean hasCustomAddress() { return this.properties.getHost() != null || this.properties.getPort() != null; } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java index b09548016ca..b487283985b 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java @@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit; import com.mongodb.ReadPreference; import com.mongodb.async.client.MongoClientSettings; +import com.mongodb.async.client.MongoClientSettings.Builder; import com.mongodb.connection.SocketSettings; import com.mongodb.connection.StreamFactory; import com.mongodb.connection.StreamFactoryFactory; @@ -37,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; /** * Tests for {@link MongoReactiveAutoConfiguration}. @@ -106,6 +108,37 @@ public class MongoReactiveAutoConfigurationTests { .isSameAs(this.context.getBean("myStreamFactoryFactory")); } + @Test + public void customizerGetsInvoked() { + this.context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of( + "spring.data.mongodb.uri:mongodb://localhost/test").applyTo(this.context); + this.context.register(PropertyPlaceholderAutoConfiguration.class, + MongoReactiveAutoConfiguration.class, MockCustomizerConfig.class); + this.context.refresh(); + assertThat(this.context.getBeanNamesForType(MongoClient.class).length) + .isEqualTo(1); + MongoClientSettingsBuilderCustomizer customizer = this.context + .getBean(MongoClientSettingsBuilderCustomizer.class); + verify(customizer).customize(any(Builder.class)); + } + + @Test + public void customizerOverridesAutoConfig() { + this.context = new AnnotationConfigApplicationContext(); + TestPropertyValues + .of("spring.data.mongodb.uri:mongodb://localhost/test?appname=auto-config") + .applyTo(this.context); + this.context.register(PropertyPlaceholderAutoConfiguration.class, + MongoReactiveAutoConfiguration.class, SimpleCustomizerConfig.class); + this.context.refresh(); + assertThat(this.context.getBeanNamesForType(MongoClient.class).length) + .isEqualTo(1); + MongoClient client = this.context.getBean(MongoClient.class); + assertThat(client.getSettings().getApplicationName()) + .isEqualTo("overridden-name"); + } + @Configuration static class OptionsConfig { @@ -138,4 +171,29 @@ public class MongoReactiveAutoConfigurationTests { } + @Configuration + static class MockCustomizerConfig { + + @Bean + public MongoClientSettingsBuilderCustomizer customizer() { + return mock(MongoClientSettingsBuilderCustomizer.class); + } + + } + + @Configuration + static class SimpleCustomizerConfig { + + @Bean + public MongoClientSettingsBuilderCustomizer customizer() { + return new MongoClientSettingsBuilderCustomizer() { + @Override + public void customize(MongoClientSettings.Builder settingsBuilder) { + settingsBuilder.applicationName("overridden-name"); + } + }; + } + + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java index 7904c2a9829..39112749d66 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java @@ -154,7 +154,7 @@ public class ReactiveMongoClientFactoryTests { private MongoClient createMongoClient(MongoProperties properties, Environment environment) { - return new ReactiveMongoClientFactory(properties, environment) + return new ReactiveMongoClientFactory(properties, environment, null) .createMongoClient(null); } From eaa34874e8890d1c96c9a98954cb5fc46322709b Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Wed, 31 May 2017 15:45:51 +0200 Subject: [PATCH 2/2] Polish "Allow customization of MongoClientSettings.Builder" Closes gh-9341 --- .../MongoClientSettingsBuilderCustomizer.java | 4 +-- .../mongo/ReactiveMongoClientFactory.java | 9 +++-- .../MongoReactiveAutoConfigurationTests.java | 35 ++----------------- .../ReactiveMongoClientFactoryTests.java | 20 +++++++++-- 4 files changed, 25 insertions(+), 43 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java index 77f8a03085f..432a316901c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientSettingsBuilderCustomizer.java @@ -31,8 +31,8 @@ public interface MongoClientSettingsBuilderCustomizer { /** * Customize the {@link Builder}. - * @param settingsBuilder the builder to customize + * @param clientSettingsBuilder the builder to customize */ - void customize(Builder settingsBuilder); + void customize(Builder clientSettingsBuilder); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java index 0d4335702f3..cf9f4c7a81c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java @@ -54,7 +54,8 @@ public class ReactiveMongoClientFactory { List builderCustomizers) { this.properties = properties; this.environment = environment; - this.builderCustomizers = builderCustomizers; + this.builderCustomizers = (builderCustomizers != null ? builderCustomizers + : Collections.emptyList()); } /** @@ -157,10 +158,8 @@ public class ReactiveMongoClientFactory { } private void customize(MongoClientSettings.Builder builder) { - if (this.builderCustomizers != null) { - for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) { - customizer.customize(builder); - } + for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) { + customizer.customize(builder); } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java index b487283985b..7196eb92bf0 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java @@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit; import com.mongodb.ReadPreference; import com.mongodb.async.client.MongoClientSettings; -import com.mongodb.async.client.MongoClientSettings.Builder; import com.mongodb.connection.SocketSettings; import com.mongodb.connection.StreamFactory; import com.mongodb.connection.StreamFactoryFactory; @@ -38,7 +37,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; /** * Tests for {@link MongoReactiveAutoConfiguration}. @@ -108,21 +106,6 @@ public class MongoReactiveAutoConfigurationTests { .isSameAs(this.context.getBean("myStreamFactoryFactory")); } - @Test - public void customizerGetsInvoked() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of( - "spring.data.mongodb.uri:mongodb://localhost/test").applyTo(this.context); - this.context.register(PropertyPlaceholderAutoConfiguration.class, - MongoReactiveAutoConfiguration.class, MockCustomizerConfig.class); - this.context.refresh(); - assertThat(this.context.getBeanNamesForType(MongoClient.class).length) - .isEqualTo(1); - MongoClientSettingsBuilderCustomizer customizer = this.context - .getBean(MongoClientSettingsBuilderCustomizer.class); - verify(customizer).customize(any(Builder.class)); - } - @Test public void customizerOverridesAutoConfig() { this.context = new AnnotationConfigApplicationContext(); @@ -171,27 +154,13 @@ public class MongoReactiveAutoConfigurationTests { } - @Configuration - static class MockCustomizerConfig { - - @Bean - public MongoClientSettingsBuilderCustomizer customizer() { - return mock(MongoClientSettingsBuilderCustomizer.class); - } - - } - @Configuration static class SimpleCustomizerConfig { @Bean public MongoClientSettingsBuilderCustomizer customizer() { - return new MongoClientSettingsBuilderCustomizer() { - @Override - public void customize(MongoClientSettings.Builder settingsBuilder) { - settingsBuilder.applicationName("overridden-name"); - } - }; + return clientSettingsBuilder -> + clientSettingsBuilder.applicationName("overridden-name"); } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java index 39112749d66..aa7871761e5 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.mongo; import java.net.UnknownHostException; +import java.util.Arrays; import java.util.List; import com.mongodb.MongoCredential; @@ -32,6 +33,9 @@ import org.springframework.core.env.Environment; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; /** * Tests for {@link ReactiveMongoClientFactory}. @@ -148,14 +152,24 @@ public class ReactiveMongoClientFactoryTests { assertServerAddress(allAddresses.get(0), "localhost", 4000); } + @Test + public void customizerIsInvoked() { + MongoProperties properties = new MongoProperties(); + MongoClientSettingsBuilderCustomizer customizer = mock( + MongoClientSettingsBuilderCustomizer.class); + createMongoClient(properties, this.environment, customizer); + verify(customizer).customize(any(MongoClientSettings.Builder.class)); + } + private MongoClient createMongoClient(MongoProperties properties) { return createMongoClient(properties, this.environment); } private MongoClient createMongoClient(MongoProperties properties, - Environment environment) { - return new ReactiveMongoClientFactory(properties, environment, null) - .createMongoClient(null); + Environment environment, + MongoClientSettingsBuilderCustomizer... customizers) { + return new ReactiveMongoClientFactory(properties, environment, + Arrays.asList(customizers)).createMongoClient(null); } private List extractServerAddresses(MongoClient client) {