From 0d61f92479f16370d51491dbf5d21c9adae36d3a Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 28 Feb 2017 19:04:18 +0100 Subject: [PATCH] Ignore URI when local.mongo.port is set This commit makes sure that if `local.mongo.port` is set, a `MongoClient` on the embedded MongoDB instance is created. When an embedded instance is detected, only the `host` property is used and the `uri` is ignored if set. This makes sure that the auto-configured `MongoClient` automatically switches to the embedded server, even if a production uri has been specified. Closes gh-8219 --- .../autoconfigure/mongo/MongoProperties.java | 90 ++++++++++--------- .../EmbeddedMongoAutoConfiguration.java | 1 - .../mongo/MongoPropertiesTests.java | 14 +++ 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java index fa69691ae6..37d5cacdca 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java @@ -202,35 +202,63 @@ public class MongoProperties { public MongoClient createMongoClient(MongoClientOptions options, Environment environment) throws UnknownHostException { try { - if (hasCustomAddress() || hasCustomCredentials()) { - if (this.uri != null) { - throw new IllegalStateException("Invalid mongo configuration, " - + "either uri or host/port/credentials must be specified"); - } - if (options == null) { - options = MongoClientOptions.builder().build(); - } - List credentials = new ArrayList(); - if (hasCustomCredentials()) { - String database = this.authenticationDatabase == null - ? getMongoClientDatabase() : this.authenticationDatabase; - credentials.add(MongoCredential.createCredential(this.username, - database, this.password)); - } - String host = this.host == null ? "localhost" : this.host; - int port = determinePort(environment); - return new MongoClient( - Collections.singletonList(new ServerAddress(host, port)), - credentials, options); + Integer embeddedPort = getEmbeddedPort(environment); + if (embeddedPort != null) { + return createEmbeddedMongoClient(options, embeddedPort); } - // The options and credentials are in the URI - return new MongoClient(new MongoClientURI(determineUri(), builder(options))); + return createNetworkMongoClient(options); } finally { clearPassword(); } } + private Integer getEmbeddedPort(Environment environment) { + if (environment != null) { + String localPort = environment.getProperty("local.mongo.port"); + if (localPort != null) { + return Integer.valueOf(localPort); + } + } + return null; + } + + private MongoClient createEmbeddedMongoClient(MongoClientOptions options, int port) { + if (options == null) { + options = MongoClientOptions.builder().build(); + } + String host = this.host == null ? "localhost" : this.host; + return new MongoClient( + Collections.singletonList(new ServerAddress(host, port)), + Collections.emptyList(), options); + } + + private MongoClient createNetworkMongoClient(MongoClientOptions options) { + if (hasCustomAddress() || hasCustomCredentials()) { + if (this.uri != null) { + throw new IllegalStateException("Invalid mongo configuration, " + + "either uri or host/port/credentials must be specified"); + } + if (options == null) { + options = MongoClientOptions.builder().build(); + } + List credentials = new ArrayList(); + if (hasCustomCredentials()) { + String database = this.authenticationDatabase == null + ? getMongoClientDatabase() : this.authenticationDatabase; + credentials.add(MongoCredential.createCredential(this.username, + database, this.password)); + } + String host = this.host == null ? "localhost" : this.host; + int port = this.port != null ? this.port : DEFAULT_PORT; + return new MongoClient( + Collections.singletonList(new ServerAddress(host, port)), + credentials, options); + } + // The options and credentials are in the URI + return new MongoClient(new MongoClientURI(determineUri(), builder(options))); + } + private boolean hasCustomAddress() { return this.host != null || this.port != null; } @@ -239,24 +267,6 @@ public class MongoProperties { return this.username != null && this.password != null; } - private int determinePort(Environment environment) { - if (this.port == null) { - return DEFAULT_PORT; - } - if (this.port == 0) { - if (environment != null) { - String localPort = environment.getProperty("local.mongo.port"); - if (localPort != null) { - return Integer.valueOf(localPort); - } - } - throw new IllegalStateException( - "spring.data.mongodb.port=0 and no local mongo port configuration " - + "is available"); - } - return this.port; - } - private Builder builder(MongoClientOptions options) { if (options != null) { return MongoClientOptions.builder(options); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java index d63391cdde..cd7a308f68 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/embedded/EmbeddedMongoAutoConfiguration.java @@ -158,7 +158,6 @@ public class EmbeddedMongoAutoConfiguration { } private void setEmbeddedPort(int port) { - this.properties.setPort(port); setPortProperty(this.context, port); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java index cd79c5e3b0..5f6d44f312 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java @@ -33,6 +33,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -49,6 +50,8 @@ public class MongoPropertiesTests { @Rule public ExpectedException thrown = ExpectedException.none(); + private MockEnvironment environment = new MockEnvironment(); + @Test public void canBindCharArrayPassword() { // gh-1572 @@ -151,6 +154,17 @@ public class MongoPropertiesTests { properties.createMongoClient(null, null); } + @Test + public void uriIsIgnoredInEmbeddedMode() throws UnknownHostException { + MongoProperties properties = new MongoProperties(); + properties.setUri("mongodb://mongo.example.com:1234/mydb"); + this.environment.setProperty("local.mongo.port", "4000"); + MongoClient client = properties.createMongoClient(null, this.environment); + List allAddresses = extractServerAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "localhost", 4000); + } + @Test public void allMongoClientOptionsCanBeSet() throws UnknownHostException { MongoClientOptions.Builder builder = MongoClientOptions.builder();