org.springframework
spring-jdbc
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfiguration.java
new file mode 100644
index 0000000000..f5371feda2
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfiguration.java
@@ -0,0 +1,76 @@
+/*
+ * 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.data.mongo;
+
+import com.mongodb.reactivestreams.client.MongoClient;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.mongo.MongoProperties;
+import org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
+import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
+import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
+import org.springframework.data.mongodb.core.convert.MongoConverter;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive mongo
+ * support.
+ *
+ * Registers a {@link ReactiveMongoTemplate} bean if no other bean of the same type is
+ * configured.
+ *
+ * Honors the {@literal spring.data.mongodb.database} property if set, otherwise connects
+ * to the {@literal test} database.
+ *
+ * @author Mark Paluch
+ * @since 2.0.0
+ */
+@Configuration
+@ConditionalOnClass({ MongoClient.class, ReactiveMongoTemplate.class })
+@EnableConfigurationProperties(MongoProperties.class)
+@AutoConfigureAfter(ReactiveMongoAutoConfiguration.class)
+public class ReactiveMongoDataAutoConfiguration {
+
+ private final MongoProperties properties;
+
+ public ReactiveMongoDataAutoConfiguration(MongoProperties properties) {
+ this.properties = properties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(ReactiveMongoDatabaseFactory.class)
+ public SimpleReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(
+ MongoClient mongo) throws Exception {
+ String database = this.properties.getMongoClientDatabase();
+ return new SimpleReactiveMongoDatabaseFactory(mongo, database);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ReactiveMongoTemplate reactiveMongoTemplate(
+ ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
+ MongoConverter converter) {
+ return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfiguration.java
new file mode 100644
index 0000000000..5b97327c85
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * 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.data.mongo;
+
+import com.mongodb.reactivestreams.client.MongoClient;
+
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
+import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
+import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
+import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Mongo Reactive
+ * Repositories.
+ *
+ * Activates when there is no bean of type
+ * {@link org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactoryBean}
+ * configured in the context, the Spring Data Mongo {@link ReactiveMongoRepository} type
+ * is on the classpath, the ReactiveStreams Mongo client driver API is on the classpath,
+ * and there is no other configured {@link ReactiveMongoRepository}.
+ *
+ * Once in effect, the auto-configuration is the equivalent of enabling Mongo repositories
+ * using the {@link EnableReactiveMongoRepositories} annotation.
+ *
+ * @author Mark Paluch
+ * @since 2.0.0
+ * @see EnableReactiveMongoRepositories
+ */
+@Configuration
+@ConditionalOnClass({ MongoClient.class, ReactiveMongoRepository.class })
+@ConditionalOnMissingBean({ MongoRepositoryFactoryBean.class,
+ ReactiveMongoRepositoryConfigurationExtension.class })
+@ConditionalOnProperty(prefix = "spring.data.mongodb.reactive-repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
+@Import(ReactiveMongoRepositoriesAutoConfigureRegistrar.class)
+@AutoConfigureAfter(ReactiveMongoDataAutoConfiguration.class)
+public class ReactiveMongoRepositoriesAutoConfiguration {
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigureRegistrar.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigureRegistrar.java
new file mode 100644
index 0000000000..08a53b6338
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigureRegistrar.java
@@ -0,0 +1,57 @@
+/*
+ * 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.data.mongo;
+
+import java.lang.annotation.Annotation;
+
+import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
+import org.springframework.data.mongodb.repository.config.ReactiveMongoRepositoryConfigurationExtension;
+import org.springframework.data.repository.config.RepositoryConfigurationExtension;
+
+/**
+ * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Mongo Reactive
+ * Repositories.
+ *
+ * @author Mark Paluch
+ * @since 2.0.0
+ */
+class ReactiveMongoRepositoriesAutoConfigureRegistrar extends
+ AbstractRepositoryConfigurationSourceSupport {
+
+ @Override
+ protected Class extends Annotation> getAnnotation() {
+ return EnableReactiveMongoRepositories.class;
+ }
+
+ @Override
+ protected Class> getConfiguration() {
+ return EnableReactiveMongoRepositoriesConfiguration.class;
+ }
+
+ @Override
+ protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
+ return new ReactiveMongoRepositoryConfigurationExtension();
+ }
+
+ @EnableReactiveMongoRepositories
+ private static class EnableReactiveMongoRepositoriesConfiguration {
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor.java
new file mode 100644
index 0000000000..318e194a0c
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.data.mongo;
+
+import com.mongodb.reactivestreams.client.MongoClient;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.boot.autoconfigure.AbstractDependsOnBeanFactoryPostProcessor;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.data.mongodb.core.ReactiveMongoClientFactoryBean;
+
+/**
+ * {@link BeanFactoryPostProcessor} to automatically set up the recommended
+ * {@link BeanDefinition#setDependsOn(String[]) dependsOn} configuration for Mongo clients
+ * when used embedded Mongo.
+ *
+ * @author Mark Paluch
+ * @since 2.0.0
+ */
+@Order(Ordered.LOWEST_PRECEDENCE)
+public class ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor extends
+ AbstractDependsOnBeanFactoryPostProcessor {
+
+ public ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor(
+ String... dependsOn) {
+ super(MongoClient.class, ReactiveMongoClientFactoryBean.class, dependsOn);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java
index 83fb675354..2774a3d3c5 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * 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.
@@ -38,6 +38,8 @@ import org.springframework.core.env.Environment;
* @author Dave Syer
* @author Oliver Gierke
* @author Phillip Webb
+ * @author Mark Paluch
+ * @author Stephane Nicoll
*/
@Configuration
@ConditionalOnClass(MongoClient.class)
@@ -45,19 +47,16 @@ import org.springframework.core.env.Environment;
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
- private final MongoProperties properties;
-
private final MongoClientOptions options;
- private final Environment environment;
+ private final MongoClientFactory factory;
private MongoClient mongo;
public MongoAutoConfiguration(MongoProperties properties,
ObjectProvider options, Environment environment) {
- this.properties = properties;
this.options = options.getIfAvailable();
- this.environment = environment;
+ this.factory = new MongoClientFactory(properties, environment);
}
@PreDestroy
@@ -70,7 +69,7 @@ public class MongoAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MongoClient mongo() throws UnknownHostException {
- this.mongo = this.properties.createMongoClient(this.options, this.environment);
+ this.mongo = this.factory.createMongoClient(this.options);
return this.mongo;
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java
new file mode 100644
index 0000000000..4acd20772b
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java
@@ -0,0 +1,130 @@
+/*
+ * 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 java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientOptions.Builder;
+import com.mongodb.MongoClientURI;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+
+import org.springframework.core.env.Environment;
+
+/**
+ * A factory for a blocking {@link MongoClient} that applies {@link MongoProperties}.
+ *
+ * @author Dave Syer
+ * @author Phillip Webb
+ * @author Josh Long
+ * @author Andy Wilkinson
+ * @author Eddú Meléndez
+ * @author Stephane Nicoll
+ * @author Nasko Vasilev
+ * @author Mark Paluch
+ * @since 2.0.0
+ */
+public class MongoClientFactory {
+
+ private final MongoProperties properties;
+ private final Environment environment;
+
+ public MongoClientFactory(MongoProperties properties, Environment environment) {
+ this.properties = properties;
+ this.environment = environment;
+ }
+
+ /**
+ * Creates a {@link MongoClient} using the given {@code options}. If the configured
+ * port is zero, the value of the {@code local.mongo.port} property is used to
+ * configure the client.
+ * @param options the options
+ * @return the Mongo client
+ * @throws UnknownHostException if the configured host is unknown
+ */
+ public MongoClient createMongoClient(MongoClientOptions options)
+ throws UnknownHostException {
+
+ if (hasCustomAddress() || hasCustomCredentials()) {
+ if (this.properties.getUri() != 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.properties.getAuthenticationDatabase() == null ? this.properties
+ .getMongoClientDatabase() : this.properties
+ .getAuthenticationDatabase();
+ credentials.add(MongoCredential.createCredential(
+ this.properties.getUsername(), database,
+ this.properties.getPassword()));
+ }
+ String host = this.properties.getHost() == null ? "localhost"
+ : this.properties.getHost();
+ int port = determinePort();
+ return new MongoClient(
+ Collections.singletonList(new ServerAddress(host, port)),
+ credentials, options);
+ }
+ // The options and credentials are in the URI
+ return new MongoClient(new MongoClientURI(this.properties.determineUri(),
+ builder(options)));
+ }
+
+ private boolean hasCustomAddress() {
+ return this.properties.getHost() != null || this.properties.getPort() != null;
+ }
+
+ private boolean hasCustomCredentials() {
+ return this.properties.getUsername() != null
+ && this.properties.getPassword() != null;
+ }
+
+ private int determinePort() {
+ if (this.properties.getPort() == null) {
+ return MongoProperties.DEFAULT_PORT;
+ }
+ if (this.properties.getPort() == 0) {
+ if (this.environment != null) {
+ String localPort = this.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.properties.getPort();
+ }
+
+ private Builder builder(MongoClientOptions options) {
+ if (options != null) {
+ return MongoClientOptions.builder(options);
+ }
+ return MongoClientOptions.builder();
+ }
+
+}
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..b47cabe29c 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * 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.
@@ -16,20 +16,9 @@
package org.springframework.boot.autoconfigure.mongo;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientOptions.Builder;
import com.mongodb.MongoClientURI;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.core.env.Environment;
/**
* Configuration properties for Mongo.
@@ -41,6 +30,7 @@ import org.springframework.core.env.Environment;
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Nasko Vasilev
+ * @author Mark Paluch
*/
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
@@ -145,15 +135,6 @@ public class MongoProperties {
this.fieldNamingStrategy = fieldNamingStrategy;
}
- public void clearPassword() {
- if (this.password == null) {
- return;
- }
- for (int i = 0; i < this.password.length; i++) {
- this.password[i] = 0;
- }
- }
-
public String getUri() {
return this.uri;
}
@@ -189,79 +170,4 @@ public class MongoProperties {
return new MongoClientURI(determineUri()).getDatabase();
}
- /**
- * Creates a {@link MongoClient} using the given {@code options} and
- * {@code environment}. If the configured port is zero, the value of the
- * {@code local.mongo.port} property retrieved from the {@code environment} is used to
- * configure the client.
- * @param options the options
- * @param environment the environment
- * @return the Mongo client
- * @throws UnknownHostException if the configured host is unknown
- */
- 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);
- }
- // The options and credentials are in the URI
- return new MongoClient(new MongoClientURI(determineUri(), builder(options)));
- }
- finally {
- clearPassword();
- }
- }
-
- private boolean hasCustomAddress() {
- return this.host != null || this.port != null;
- }
-
- private boolean hasCustomCredentials() {
- 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);
- }
- return MongoClientOptions.builder();
- }
-
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfiguration.java
new file mode 100644
index 0000000000..cfcd64a82a
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfiguration.java
@@ -0,0 +1,71 @@
+/*
+ * 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 javax.annotation.PreDestroy;
+
+import com.mongodb.async.client.MongoClientSettings;
+import com.mongodb.reactivestreams.client.MongoClient;
+
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+/**
+ * {@link EnableAutoConfiguration Auto-configuration} for Reactive Mongo.
+ *
+ * @author Mark Paluch
+ * @author Stephane Nicoll
+ * @since 2.0.0
+ */
+@Configuration
+@ConditionalOnClass(MongoClient.class)
+@EnableConfigurationProperties(MongoProperties.class)
+public class ReactiveMongoAutoConfiguration {
+
+ private final MongoClientSettings settings;
+
+ private final ReactiveMongoClientFactory factory;
+
+ private MongoClient mongo;
+
+ public ReactiveMongoAutoConfiguration(MongoProperties properties,
+ ObjectProvider settings, Environment environment) {
+ this.settings = settings.getIfAvailable();
+ this.factory = new ReactiveMongoClientFactory(properties, environment);
+ }
+
+ @PreDestroy
+ public void close() {
+ if (this.mongo != null) {
+ this.mongo.close();
+ }
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public MongoClient reactiveStreamsMongoClient() {
+ this.mongo = this.factory.createMongoClient(this.settings);
+ return this.mongo;
+ }
+
+}
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
new file mode 100644
index 0000000000..1a38ce47e4
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java
@@ -0,0 +1,165 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.async.client.MongoClientSettings;
+import com.mongodb.async.client.MongoClientSettings.Builder;
+import com.mongodb.connection.ClusterSettings;
+import com.mongodb.connection.ConnectionPoolSettings;
+import com.mongodb.connection.ServerSettings;
+import com.mongodb.connection.SocketSettings;
+import com.mongodb.connection.SslSettings;
+import com.mongodb.reactivestreams.client.MongoClient;
+import com.mongodb.reactivestreams.client.MongoClients;
+
+import org.springframework.core.env.Environment;
+
+/**
+ * A factory for a reactive {@link MongoClient} that applies {@link MongoProperties}.
+ *
+ * @author Mark Paluch
+ * @author Stephane Nicoll
+ * @since 2.0.0
+ */
+public class ReactiveMongoClientFactory {
+
+ private final MongoProperties properties;
+
+ private final Environment environment;
+
+ public ReactiveMongoClientFactory(MongoProperties properties,
+ Environment environment) {
+ this.properties = properties;
+ this.environment = environment;
+ }
+
+ /**
+ * Creates a {@link MongoClient} using the given {@code options}. If the configured
+ * port is zero, the value of the {@code local.mongo.port} property is used to
+ * configure the client.
+ * @param settings the settings
+ * @return the Mongo client
+ */
+ public MongoClient createMongoClient(MongoClientSettings settings) {
+ if (hasCustomAddress() || hasCustomCredentials()) {
+ if (this.properties.getUri() != null) {
+ throw new IllegalStateException("Invalid mongo configuration, "
+ + "either uri or host/port/credentials must be specified");
+ }
+
+ Builder builder = builder(settings);
+ if (hasCustomCredentials()) {
+ List credentials = new ArrayList();
+ String database = this.properties.getAuthenticationDatabase() == null ? this.properties
+ .getMongoClientDatabase() : this.properties
+ .getAuthenticationDatabase();
+ credentials.add(MongoCredential.createCredential(
+ this.properties.getUsername(), database,
+ this.properties.getPassword()));
+ builder.credentialList(credentials);
+ }
+ String host = this.properties.getHost() == null ? "localhost"
+ : this.properties.getHost();
+ int port = determinePort();
+ ClusterSettings clusterSettings = ClusterSettings.builder()
+ .hosts(Collections.singletonList(new ServerAddress(host, port)))
+ .build();
+ builder.clusterSettings(clusterSettings);
+ return MongoClients.create(builder.build());
+ }
+ ConnectionString connectionString = new ConnectionString(
+ this.properties.determineUri());
+ return MongoClients.create(createBuilder(settings, connectionString).build());
+ }
+
+ private Builder createBuilder(MongoClientSettings settings,
+ ConnectionString connectionString) {
+ Builder builder = builder(settings)
+ .clusterSettings(
+ ClusterSettings.builder().applyConnectionString(connectionString)
+ .build())
+ .connectionPoolSettings(
+ ConnectionPoolSettings.builder()
+ .applyConnectionString(connectionString).build())
+ .serverSettings(
+ ServerSettings.builder().applyConnectionString(connectionString)
+ .build())
+ .credentialList(connectionString.getCredentialList())
+ .sslSettings(
+ SslSettings.builder().applyConnectionString(connectionString)
+ .build())
+ .socketSettings(
+ SocketSettings.builder().applyConnectionString(connectionString)
+ .build());
+ if (connectionString.getReadPreference() != null) {
+ builder.readPreference(connectionString.getReadPreference());
+ }
+ if (connectionString.getReadConcern() != null) {
+ builder.readConcern(connectionString.getReadConcern());
+ }
+ if (connectionString.getWriteConcern() != null) {
+ builder.writeConcern(connectionString.getWriteConcern());
+ }
+ if (connectionString.getApplicationName() != null) {
+ builder.applicationName(connectionString.getApplicationName());
+ }
+ return builder;
+ }
+
+ private boolean hasCustomAddress() {
+ return this.properties.getHost() != null || this.properties.getPort() != null;
+ }
+
+ private boolean hasCustomCredentials() {
+ return this.properties.getUsername() != null
+ && this.properties.getPassword() != null;
+ }
+
+ private int determinePort() {
+ if (this.properties.getPort() == null) {
+ return MongoProperties.DEFAULT_PORT;
+ }
+ if (this.properties.getPort() == 0) {
+ if (this.environment != null) {
+ String localPort = this.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.properties.getPort();
+ }
+
+ private Builder builder(MongoClientSettings settings) {
+ if (settings == null) {
+ return MongoClientSettings.builder();
+ }
+
+ return MongoClientSettings.builder(settings);
+ }
+
+}
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..d576c1d93d 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
@@ -53,6 +53,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.mongo.MongoClientDependsOnBeanFactoryPostProcessor;
+import org.springframework.boot.autoconfigure.data.mongo.ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -64,6 +65,7 @@ import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
+import org.springframework.data.mongodb.core.ReactiveMongoClientFactoryBean;
import org.springframework.util.Assert;
/**
@@ -72,6 +74,7 @@ import org.springframework.util.Assert;
* @author Henryk Konsek
* @author Andy Wilkinson
* @author Yogesh Lonkar
+ * @author Mark Paluch
* @since 1.3.0
*/
@Configuration
@@ -226,6 +229,22 @@ public class EmbeddedMongoAutoConfiguration {
}
+ /**
+ * Additional configuration to ensure that {@link MongoClient} beans depend on the
+ * {@code embeddedMongoServer} bean.
+ */
+ @Configuration
+ @ConditionalOnClass({ com.mongodb.reactivestreams.client.MongoClient.class,
+ ReactiveMongoClientFactoryBean.class })
+ protected static class EmbeddedReactiveMongoDependencyConfiguration extends
+ ReactiveStreamsMongoClientDependsOnBeanFactoryPostProcessor {
+
+ public EmbeddedReactiveMongoDependencyConfiguration() {
+ super("embeddedMongoServer");
+ }
+
+ }
+
/**
* A workaround for the lack of a {@code toString} implementation on
* {@code GenericFeatureAwareVersion}.
diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index e097896216..4d7ab3e894 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -112,6 +112,12 @@
"description": "Enable LDAP repositories.",
"defaultValue": true
},
+ {
+ "name": "spring.data.mongodb.reactive-repositories.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable Mongo reactive repositories.",
+ "defaultValue": true
+ },
{
"name": "spring.data.mongodb.repositories.enabled",
"type": "java.lang.Boolean",
diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
index e4c64257fb..415bc5c874 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -41,6 +41,8 @@ org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
+org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoDataAutoConfiguration,\
+org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
@@ -83,6 +85,7 @@ org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoCo
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
+org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/mongo/ReactiveCityMongoDbRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/mongo/ReactiveCityMongoDbRepository.java
new file mode 100644
index 0000000000..5ac5d2ec3b
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/mongo/ReactiveCityMongoDbRepository.java
@@ -0,0 +1,25 @@
+/*
+ * 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.data.alt.mongo;
+
+import org.springframework.boot.autoconfigure.data.mongo.city.City;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+
+public interface ReactiveCityMongoDbRepository
+ extends ReactiveCrudRepository {
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveAndBlockingMongoRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveAndBlockingMongoRepositoriesAutoConfigurationTests.java
new file mode 100644
index 0000000000..a32235908b
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveAndBlockingMongoRepositoriesAutoConfigurationTests.java
@@ -0,0 +1,102 @@
+/*
+ * 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.data.mongo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Test;
+
+import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
+import org.springframework.boot.autoconfigure.data.mongo.city.CityRepository;
+import org.springframework.boot.autoconfigure.data.mongo.city.ReactiveCityRepository;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfigurationTests;
+import org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link MongoRepositoriesAutoConfiguration} and
+ * {@link ReactiveMongoRepositoriesAutoConfiguration}.
+ *
+ * @author Mark Paluch
+ */
+public class ReactiveAndBlockingMongoRepositoriesAutoConfigurationTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ this.context.close();
+ }
+
+ @Test
+ public void shouldCreateInstancesForReactiveAndBlockingRepositories()
+ throws Exception {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.datasource.initialize:false");
+ this.context.register(BlockingAndReactiveConfiguration.class,
+ BaseConfiguration.class);
+ this.context.refresh();
+ assertThat(this.context.getBean(CityRepository.class)).isNotNull();
+ assertThat(this.context.getBean(ReactiveCityRepository.class)).isNotNull();
+ }
+
+ @Configuration
+ @TestAutoConfigurationPackage(MongoAutoConfigurationTests.class)
+ @EnableMongoRepositories(basePackageClasses = ReactiveCityRepository.class)
+ @EnableReactiveMongoRepositories(basePackageClasses = ReactiveCityRepository.class)
+ protected static class BlockingAndReactiveConfiguration {
+
+ }
+
+ @Configuration
+ @Import(Registrar.class)
+ protected static class BaseConfiguration {
+
+ }
+
+ protected static class Registrar implements ImportSelector {
+
+ @Override
+ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+ List names = new ArrayList();
+ for (Class> type : new Class>[] { MongoAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class,
+ MongoDataAutoConfiguration.class,
+ MongoRepositoriesAutoConfiguration.class,
+ ReactiveMongoDataAutoConfiguration.class,
+ ReactiveMongoRepositoriesAutoConfiguration.class }) {
+ names.add(type.getName());
+ }
+ return names.toArray(new String[0]);
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfigurationTests.java
new file mode 100644
index 0000000000..b9efde7d62
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoDataAutoConfigurationTests.java
@@ -0,0 +1,56 @@
+/*
+ * 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.data.mongo;
+
+import org.junit.After;
+import org.junit.Test;
+
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ReactiveMongoDataAutoConfiguration}.
+ *
+ * @author Mark Paluch
+ */
+public class ReactiveMongoDataAutoConfigurationTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void templateExists() {
+ this.context = new AnnotationConfigApplicationContext(
+ PropertyPlaceholderAutoConfiguration.class, MongoAutoConfiguration.class,
+ MongoDataAutoConfiguration.class, ReactiveMongoAutoConfiguration.class,
+ ReactiveMongoDataAutoConfiguration.class);
+ assertThat(this.context.getBeanNamesForType(ReactiveMongoTemplate.class))
+ .hasSize(1);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigurationTests.java
new file mode 100644
index 0000000000..ea24dad649
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/ReactiveMongoRepositoriesAutoConfigurationTests.java
@@ -0,0 +1,136 @@
+/*
+ * 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.data.mongo;
+
+import java.util.Set;
+
+import com.mongodb.reactivestreams.client.MongoClient;
+import org.junit.After;
+import org.junit.Test;
+
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.alt.mongo.CityMongoDbRepository;
+import org.springframework.boot.autoconfigure.data.alt.mongo.ReactiveCityMongoDbRepository;
+import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
+import org.springframework.boot.autoconfigure.data.mongo.city.City;
+import org.springframework.boot.autoconfigure.data.mongo.city.ReactiveCityRepository;
+import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
+import org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ReactiveMongoRepositoriesAutoConfiguration}.
+ *
+ * @author Mark Paluch
+ */
+public class ReactiveMongoRepositoriesAutoConfigurationTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void testDefaultRepositoryConfiguration() throws Exception {
+ prepareApplicationContext(TestConfiguration.class);
+
+ assertThat(this.context.getBean(ReactiveCityRepository.class)).isNotNull();
+ MongoClient client = this.context.getBean(MongoClient.class);
+ assertThat(client).isInstanceOf(MongoClient.class);
+ MongoMappingContext mappingContext = this.context
+ .getBean(MongoMappingContext.class);
+ @SuppressWarnings("unchecked")
+ Set extends Class>> entities = (Set extends Class>>) ReflectionTestUtils
+ .getField(mappingContext, "initialEntitySet");
+ assertThat(entities).hasSize(1);
+ }
+
+ @Test
+ public void testNoRepositoryConfiguration() throws Exception {
+ prepareApplicationContext(EmptyConfiguration.class);
+
+ MongoClient client = this.context.getBean(MongoClient.class);
+ assertThat(client).isInstanceOf(MongoClient.class);
+ }
+
+ @Test
+ public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
+ prepareApplicationContext(CustomizedConfiguration.class);
+
+ assertThat(this.context.getBeansOfType(ReactiveCityMongoDbRepository.class)).isEmpty();
+ }
+
+ @Test(expected = NoSuchBeanDefinitionException.class)
+ public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
+ prepareApplicationContext(SortOfInvalidCustomConfiguration.class);
+
+ this.context.getBean(ReactiveCityRepository.class);
+ }
+
+ private void prepareApplicationContext(Class>... configurationClasses) {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(configurationClasses);
+ this.context.register(MongoAutoConfiguration.class,
+ MongoDataAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class,
+ ReactiveMongoDataAutoConfiguration.class,
+ ReactiveMongoRepositoriesAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ }
+
+ @Configuration
+ @TestAutoConfigurationPackage(City.class)
+ protected static class TestConfiguration {
+
+ }
+
+ @Configuration
+ @TestAutoConfigurationPackage(EmptyDataPackage.class)
+ protected static class EmptyConfiguration {
+
+ }
+
+ @Configuration
+ @TestAutoConfigurationPackage(ReactiveMongoRepositoriesAutoConfigurationTests.class)
+ @EnableMongoRepositories(basePackageClasses = CityMongoDbRepository.class)
+ protected static class CustomizedConfiguration {
+
+ }
+
+ @Configuration
+ // To not find any repositories
+ @EnableReactiveMongoRepositories("foo.bar")
+ @TestAutoConfigurationPackage(ReactiveMongoRepositoriesAutoConfigurationTests.class)
+ protected static class SortOfInvalidCustomConfiguration {
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/city/ReactiveCityRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/city/ReactiveCityRepository.java
new file mode 100644
index 0000000000..4c4e3f0cc2
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/mongo/city/ReactiveCityRepository.java
@@ -0,0 +1,27 @@
+/*
+ * 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.data.mongo.city;
+
+import reactor.core.publisher.Flux;
+
+import org.springframework.data.repository.Repository;
+
+public interface ReactiveCityRepository extends Repository {
+
+ Flux findAll();
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java
new file mode 100644
index 0000000000..6126d68474
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java
@@ -0,0 +1,173 @@
+/*
+ * 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 java.net.UnknownHostException;
+import java.util.List;
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.connection.Cluster;
+import com.mongodb.connection.ClusterSettings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link MongoClientFactory}.
+ *
+ * @author Phillip Webb
+ * @author Andy Wilkinson
+ * @author Stephane Nicoll
+ * @author Mark Paluch
+ */
+public class MongoClientFactoryTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void portCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setPort(12345);
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(1);
+ assertServerAddress(allAddresses.get(0), "localhost", 12345);
+ }
+
+ @Test
+ public void hostCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setHost("mongo.example.com");
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(1);
+ assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
+ }
+
+ @Test
+ public void credentialsCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
+ "test");
+ }
+
+ @Test
+ public void databaseCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setDatabase("foo");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
+ "foo");
+ }
+
+ @Test
+ public void authenticationDatabaseCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setAuthenticationDatabase("foo");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
+ "foo");
+ }
+
+ @Test
+ public void uriCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://user:secret@mongo1.example.com:12345,"
+ + "mongo2.example.com:23456/test");
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(2);
+ assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
+ assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
+ List credentialsList = client.getCredentialsList();
+ assertThat(credentialsList).hasSize(1);
+ assertMongoCredential(credentialsList.get(0), "user", "secret", "test");
+ }
+
+ @Test
+ public void uriCannotBeSetWithCredentials() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://127.0.0.1:1234/mydb");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ this.thrown.expect(IllegalStateException.class);
+ this.thrown.expectMessage("Invalid mongo configuration, "
+ + "either uri or host/port/credentials must be specified");
+ createMongoClient(properties);
+ }
+
+ @Test
+ public void uriCannotBeSetWithHostPort() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://127.0.0.1:1234/mydb");
+ properties.setHost("localhost");
+ properties.setPort(4567);
+ this.thrown.expect(IllegalStateException.class);
+ this.thrown.expectMessage("Invalid mongo configuration, "
+ + "either uri or host/port/credentials must be specified");
+ createMongoClient(properties);
+ }
+
+ private MongoClient createMongoClient(MongoProperties properties)
+ throws UnknownHostException {
+ return new MongoClientFactory(properties, null).createMongoClient(null);
+ }
+
+ private List extractServerAddresses(MongoClient client) {
+ Cluster cluster = (Cluster) ReflectionTestUtils.getField(client, "cluster");
+ ClusterSettings clusterSettings = (ClusterSettings) ReflectionTestUtils
+ .getField(cluster, "settings");
+ List allAddresses = clusterSettings.getHosts();
+ return allAddresses;
+ }
+
+ private void assertServerAddress(ServerAddress serverAddress, String expectedHost,
+ int expectedPort) {
+ assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
+ assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
+ }
+
+ private void assertMongoCredential(MongoCredential credentials,
+ String expectedUsername, String expectedPassword, String expectedSource) {
+ assertThat(credentials.getUserName()).isEqualTo(expectedUsername);
+ assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray());
+ assertThat(credentials.getSource()).isEqualTo(expectedSource);
+ }
+
+ @Configuration
+ @EnableConfigurationProperties(MongoProperties.class)
+ static class Config {
+
+ }
+
+}
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..504e807f8b 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2016 the original author or authors.
+ * 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.
@@ -17,14 +17,9 @@
package org.springframework.boot.autoconfigure.mongo;
import java.net.UnknownHostException;
-import java.util.List;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
-import com.mongodb.connection.Cluster;
-import com.mongodb.connection.ClusterSettings;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -33,7 +28,6 @@ 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.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -43,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Phillip Webb
* @author Andy Wilkinson
* @author Stephane Nicoll
+ * @author Mark Paluch
*/
public class MongoPropertiesTests {
@@ -60,97 +55,6 @@ public class MongoPropertiesTests {
assertThat(properties.getPassword()).isEqualTo("word".toCharArray());
}
- @Test
- public void portCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setPort(12345);
- MongoClient client = properties.createMongoClient(null, null);
- List allAddresses = extractServerAddresses(client);
- assertThat(allAddresses).hasSize(1);
- assertServerAddress(allAddresses.get(0), "localhost", 12345);
- }
-
- @Test
- public void hostCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setHost("mongo.example.com");
- MongoClient client = properties.createMongoClient(null, null);
- List allAddresses = extractServerAddresses(client);
- assertThat(allAddresses).hasSize(1);
- assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
- }
-
- @Test
- public void credentialsCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setUsername("user");
- properties.setPassword("secret".toCharArray());
- MongoClient client = properties.createMongoClient(null, null);
- assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
- "test");
- }
-
- @Test
- public void databaseCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setDatabase("foo");
- properties.setUsername("user");
- properties.setPassword("secret".toCharArray());
- MongoClient client = properties.createMongoClient(null, null);
- assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
- "foo");
- }
-
- @Test
- public void authenticationDatabaseCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setAuthenticationDatabase("foo");
- properties.setUsername("user");
- properties.setPassword("secret".toCharArray());
- MongoClient client = properties.createMongoClient(null, null);
- assertMongoCredential(client.getCredentialsList().get(0), "user", "secret",
- "foo");
- }
-
- @Test
- public void uriCanBeCustomized() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setUri("mongodb://user:secret@mongo1.example.com:12345,"
- + "mongo2.example.com:23456/test");
- MongoClient client = properties.createMongoClient(null, null);
- List allAddresses = extractServerAddresses(client);
- assertThat(allAddresses).hasSize(2);
- assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
- assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
- List credentialsList = client.getCredentialsList();
- assertThat(credentialsList).hasSize(1);
- assertMongoCredential(credentialsList.get(0), "user", "secret", "test");
- }
-
- @Test
- public void uriCannotBeSetWithCredentials() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setUri("mongodb://127.0.0.1:1234/mydb");
- properties.setUsername("user");
- properties.setPassword("secret".toCharArray());
- this.thrown.expect(IllegalStateException.class);
- this.thrown.expectMessage("Invalid mongo configuration, "
- + "either uri or host/port/credentials must be specified");
- properties.createMongoClient(null, null);
- }
-
- @Test
- public void uriCannotBeSetWithHostPort() throws UnknownHostException {
- MongoProperties properties = new MongoProperties();
- properties.setUri("mongodb://127.0.0.1:1234/mydb");
- properties.setHost("localhost");
- properties.setPort(4567);
- this.thrown.expect(IllegalStateException.class);
- this.thrown.expectMessage("Invalid mongo configuration, "
- + "either uri or host/port/credentials must be specified");
- properties.createMongoClient(null, null);
- }
-
@Test
public void allMongoClientOptionsCanBeSet() throws UnknownHostException {
MongoClientOptions.Builder builder = MongoClientOptions.builder();
@@ -174,7 +78,8 @@ public class MongoPropertiesTests {
builder.requiredReplicaSetName("testReplicaSetName");
MongoClientOptions options = builder.build();
MongoProperties properties = new MongoProperties();
- MongoClient client = properties.createMongoClient(options, null);
+ MongoClient client = new MongoClientFactory(properties, null)
+ .createMongoClient(options);
MongoClientOptions wrapped = client.getMongoClientOptions();
assertThat(wrapped.isAlwaysUseMBeans()).isEqualTo(options.isAlwaysUseMBeans());
assertThat(wrapped.getConnectionsPerHost())
@@ -207,27 +112,6 @@ public class MongoPropertiesTests {
.isEqualTo(options.getRequiredReplicaSetName());
}
- private List extractServerAddresses(MongoClient client) {
- Cluster cluster = (Cluster) ReflectionTestUtils.getField(client, "cluster");
- ClusterSettings clusterSettings = (ClusterSettings) ReflectionTestUtils
- .getField(cluster, "settings");
- List allAddresses = clusterSettings.getHosts();
- return allAddresses;
- }
-
- private void assertServerAddress(ServerAddress serverAddress, String expectedHost,
- int expectedPort) {
- assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
- assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
- }
-
- private void assertMongoCredential(MongoCredential credentials,
- String expectedUsername, String expectedPassword, String expectedSource) {
- assertThat(credentials.getUserName()).isEqualTo(expectedUsername);
- assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray());
- assertThat(credentials.getSource()).isEqualTo(expectedSource);
- }
-
@Configuration
@EnableConfigurationProperties(MongoProperties.class)
static class Config {
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfigurationTests.java
new file mode 100644
index 0000000000..bbc8360012
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoAutoConfigurationTests.java
@@ -0,0 +1,140 @@
+/*
+ * 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 java.util.concurrent.TimeUnit;
+
+import com.mongodb.ReadPreference;
+import com.mongodb.async.client.MongoClientSettings;
+import com.mongodb.connection.SocketSettings;
+import com.mongodb.connection.StreamFactory;
+import com.mongodb.connection.StreamFactoryFactory;
+import com.mongodb.reactivestreams.client.MongoClient;
+import org.junit.After;
+import org.junit.Test;
+
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.test.util.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+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;
+
+/**
+ * Tests for {@link ReactiveMongoAutoConfiguration}.
+ *
+ * @author Mark Paluch
+ */
+public class ReactiveMongoAutoConfigurationTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void clientExists() {
+ this.context = new AnnotationConfigApplicationContext(
+ PropertyPlaceholderAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class);
+ assertThat(this.context.getBeanNamesForType(MongoClient.class).length).isEqualTo(1);
+ }
+
+ @Test
+ public void optionsAdded() {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.data.mongodb.host:localhost");
+ this.context.register(OptionsConfig.class,
+ PropertyPlaceholderAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class);
+ this.context.refresh();
+ assertThat(this.context.getBean(MongoClient.class).getSettings()
+ .getSocketSettings().getReadTimeout(TimeUnit.SECONDS)).isEqualTo(300);
+ }
+
+ @Test
+ public void optionsAddedButNoHost() {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.data.mongodb.uri:mongodb://localhost/test");
+ this.context.register(OptionsConfig.class,
+ PropertyPlaceholderAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class);
+ this.context.refresh();
+ assertThat(this.context.getBean(MongoClient.class).getSettings()
+ .getReadPreference()).isEqualTo(ReadPreference.nearest());
+ }
+
+ @Test
+ public void optionsSslConfig() {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "spring.data.mongodb.uri:mongodb://localhost/test");
+ this.context.register(SslOptionsConfig.class,
+ PropertyPlaceholderAutoConfiguration.class,
+ ReactiveMongoAutoConfiguration.class);
+ this.context.refresh();
+ MongoClient mongo = this.context.getBean(MongoClient.class);
+ MongoClientSettings settings = mongo.getSettings();
+ assertThat(settings.getApplicationName()).isEqualTo("test-config");
+ assertThat(settings.getStreamFactoryFactory())
+ .isSameAs(this.context.getBean("myStreamFactoryFactory"));
+ }
+
+ @Configuration
+ static class OptionsConfig {
+
+ @Bean
+ public MongoClientSettings mongoClientSettings() {
+ return MongoClientSettings
+ .builder()
+ .readPreference(ReadPreference.nearest())
+ .socketSettings(
+ SocketSettings.builder().readTimeout(300, TimeUnit.SECONDS)
+ .build()).build();
+ }
+
+ }
+
+ @Configuration
+ static class SslOptionsConfig {
+
+ @Bean
+ public MongoClientSettings mongoClientSettings() {
+ return MongoClientSettings.builder().applicationName("test-config")
+ .streamFactoryFactory(myStreamFactoryFactory()).build();
+ }
+
+ @Bean
+ public StreamFactoryFactory myStreamFactoryFactory() {
+ StreamFactoryFactory streamFactoryFactory = mock(StreamFactoryFactory.class);
+ given(streamFactoryFactory.create(any(), any())).willReturn(mock(StreamFactory.class));
+ return streamFactoryFactory;
+ }
+
+ }
+
+}
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
new file mode 100644
index 0000000000..651d733ef2
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java
@@ -0,0 +1,163 @@
+/*
+ * 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 java.net.UnknownHostException;
+import java.util.List;
+
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.async.client.MongoClientSettings;
+import com.mongodb.connection.ClusterSettings;
+import com.mongodb.reactivestreams.client.MongoClient;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ReactiveMongoClientFactory}.
+ *
+ * @author Mark Paluch
+ */
+public class ReactiveMongoClientFactoryTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void portCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setPort(12345);
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(1);
+ assertServerAddress(allAddresses.get(0), "localhost", 12345);
+ }
+
+ @Test
+ public void hostCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setHost("mongo.example.com");
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(1);
+ assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017);
+ }
+
+ @Test
+ public void credentialsCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(extractMongoCredentials(client).get(0), "user", "secret",
+ "test");
+ }
+
+ @Test
+ public void databaseCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setDatabase("foo");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(extractMongoCredentials(client).get(0), "user", "secret",
+ "foo");
+ }
+
+ @Test
+ public void authenticationDatabaseCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setAuthenticationDatabase("foo");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ MongoClient client = createMongoClient(properties);
+ assertMongoCredential(extractMongoCredentials(client).get(0), "user", "secret",
+ "foo");
+ }
+
+ @Test
+ public void uriCanBeCustomized() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://user:secret@mongo1.example.com:12345,"
+ + "mongo2.example.com:23456/test");
+ MongoClient client = createMongoClient(properties);
+ List allAddresses = extractServerAddresses(client);
+ assertThat(allAddresses).hasSize(2);
+ assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
+ assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
+ List credentialsList = extractMongoCredentials(client);
+ assertThat(credentialsList).hasSize(1);
+ assertMongoCredential(credentialsList.get(0), "user", "secret", "test");
+ }
+
+ @Test
+ public void uriCannotBeSetWithCredentials() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://127.0.0.1:1234/mydb");
+ properties.setUsername("user");
+ properties.setPassword("secret".toCharArray());
+ this.thrown.expect(IllegalStateException.class);
+ this.thrown.expectMessage("Invalid mongo configuration, "
+ + "either uri or host/port/credentials must be specified");
+ createMongoClient(properties);
+ }
+
+ @Test
+ public void uriCannotBeSetWithHostPort() throws UnknownHostException {
+ MongoProperties properties = new MongoProperties();
+ properties.setUri("mongodb://127.0.0.1:1234/mydb");
+ properties.setHost("localhost");
+ properties.setPort(4567);
+ this.thrown.expect(IllegalStateException.class);
+ this.thrown.expectMessage("Invalid mongo configuration, "
+ + "either uri or host/port/credentials must be specified");
+ createMongoClient(properties);
+ }
+
+ private MongoClient createMongoClient(MongoProperties properties) {
+ return new ReactiveMongoClientFactory(properties, null).createMongoClient(null);
+ }
+
+ private List extractServerAddresses(MongoClient client) {
+ MongoClientSettings settings = client.getSettings();
+ ClusterSettings clusterSettings = settings.getClusterSettings();
+ List allAddresses = clusterSettings.getHosts();
+ return allAddresses;
+ }
+
+ private List extractMongoCredentials(MongoClient client) {
+ MongoClientSettings settings = client.getSettings();
+ return settings.getCredentialList();
+ }
+
+ private void assertServerAddress(ServerAddress serverAddress, String expectedHost,
+ int expectedPort) {
+ assertThat(serverAddress.getHost()).isEqualTo(expectedHost);
+ assertThat(serverAddress.getPort()).isEqualTo(expectedPort);
+ }
+
+ private void assertMongoCredential(MongoCredential credentials,
+ String expectedUsername, String expectedPassword, String expectedSource) {
+ assertThat(credentials.getUserName()).isEqualTo(expectedUsername);
+ assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray());
+ assertThat(credentials.getSource()).isEqualTo(expectedSource);
+ }
+
+}
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index cb061fd130..fba3daff26 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -376,6 +376,11 @@
spring-boot-starter-data-mongodb
2.0.0.BUILD-SNAPSHOT
+