mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Provide a starter for reactive Spring Data MongoDB
Add autoconfiguration to bootstrap MongoDB Reactive Streams driver components, reactive Spring Data MongoDB and reactive repositories. Add bean dependency processor for flapdoodle so embedded MongoDB instances are configured before bootstraping the reactive MongoDB client. Add Spring Data MongoDB Reactive starter with blocking and non-blocking dependencies. MongoDB requires a separate driver that is used in the `ReactiveMongoTemplate` while `MappingMongoConverter` (shared amongst blocking/reactive Template API) requires the blocking driver to resolve DBRefs. See gh-8230
This commit is contained in:
parent
13791cad53
commit
48b0f1577b
@ -100,6 +100,16 @@
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-async</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-reactivestreams</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.cache</groupId>
|
||||
<artifactId>cache-api</artifactId>
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* Registers a {@link ReactiveMongoTemplate} bean if no other bean of the same type is
|
||||
* configured.
|
||||
* <P>
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
@ -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.
|
||||
* <p>
|
||||
* 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}.
|
||||
* <p>
|
||||
* 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 {
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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,7 @@ import org.springframework.core.env.Environment;
|
||||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
* @author Phillip Webb
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(MongoClient.class)
|
||||
@ -51,6 +52,8 @@ public class MongoAutoConfiguration {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final MongoClientFactory factory;
|
||||
|
||||
private MongoClient mongo;
|
||||
|
||||
public MongoAutoConfiguration(MongoProperties properties,
|
||||
@ -58,6 +61,7 @@ public class MongoAutoConfiguration {
|
||||
this.properties = properties;
|
||||
this.options = options.getIfAvailable();
|
||||
this.environment = environment;
|
||||
this.factory = new MongoClientFactory(properties);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@ -70,7 +74,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, this.environment);
|
||||
return this.mongo;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 Mark Paluch
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class MongoClientFactory {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
public MongoClientFactory(MongoProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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<MongoCredential> credentials = new ArrayList<MongoCredential>();
|
||||
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(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(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(Environment environment) {
|
||||
if (this.properties.getPort() == null) {
|
||||
return MongoProperties.DEFAULT_PORT;
|
||||
}
|
||||
if (this.properties.getPort() == 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.properties.getPort();
|
||||
}
|
||||
|
||||
private Builder builder(MongoClientOptions options) {
|
||||
if (options != null) {
|
||||
return MongoClientOptions.builder(options);
|
||||
}
|
||||
return MongoClientOptions.builder();
|
||||
}
|
||||
}
|
@ -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 {
|
||||
@ -189,79 +179,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<MongoCredential> credentials = new ArrayList<MongoCredential>();
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.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
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(MongoClient.class)
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
public class ReactiveMongoAutoConfiguration {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
private final MongoClientSettings settings;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final ReactiveMongoClientFactory factory;
|
||||
|
||||
private MongoClient mongo;
|
||||
|
||||
public ReactiveMongoAutoConfiguration(MongoProperties properties,
|
||||
ObjectProvider<MongoClientSettings> settings, Environment environment) {
|
||||
this.properties = properties;
|
||||
this.settings = settings.getIfAvailable();
|
||||
this.environment = environment;
|
||||
this.factory = new ReactiveMongoClientFactory(properties);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
if (this.mongo != null) {
|
||||
this.mongo.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoClient reactiveStreamsMongoClient() {
|
||||
this.mongo = this.factory.createMongoClient(this.settings, this.environment);
|
||||
return this.mongo;
|
||||
}
|
||||
|
||||
}
|
@ -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.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
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ReactiveMongoClientFactory {
|
||||
|
||||
private final MongoProperties properties;
|
||||
|
||||
public ReactiveMongoClientFactory(MongoProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 settings the settings
|
||||
* @param environment the environment
|
||||
* @return the Mongo client
|
||||
*/
|
||||
public MongoClient createMongoClient(MongoClientSettings settings,
|
||||
Environment environment) {
|
||||
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<MongoCredential> credentials = new ArrayList<MongoCredential>();
|
||||
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(environment);
|
||||
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(Environment environment) {
|
||||
if (this.properties.getPort() == null) {
|
||||
return MongoProperties.DEFAULT_PORT;
|
||||
}
|
||||
if (this.properties.getPort() == 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.properties.getPort();
|
||||
}
|
||||
|
||||
private Builder builder(MongoClientSettings settings) {
|
||||
if (settings == null) {
|
||||
return MongoClientSettings.builder();
|
||||
}
|
||||
|
||||
return MongoClientSettings.builder(settings);
|
||||
}
|
||||
|
||||
}
|
@ -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,21 @@ 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}.
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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<City, Long> {
|
||||
|
||||
}
|
@ -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<String> names = new ArrayList<String>();
|
||||
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]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
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 {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
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).length)
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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() {
|
||||
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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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<City, Long> {
|
||||
|
||||
Flux<City> findAll();
|
||||
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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} via {@link MongoProperties}.
|
||||
*
|
||||
* @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 = new MongoClientFactory(properties).createMongoClient(null, null);
|
||||
List<ServerAddress> 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 = new MongoClientFactory(properties).createMongoClient(null, null);
|
||||
List<ServerAddress> 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 = new MongoClientFactory(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 = new MongoClientFactory(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 = new MongoClientFactory(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 = new MongoClientFactory(properties).createMongoClient(null, null);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(2);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
List<MongoCredential> 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");
|
||||
new MongoClientFactory(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");
|
||||
new MongoClientFactory(properties).createMongoClient(null, null);
|
||||
}
|
||||
|
||||
private List<ServerAddress> extractServerAddresses(MongoClient client) {
|
||||
Cluster cluster = (Cluster) ReflectionTestUtils.getField(client, "cluster");
|
||||
ClusterSettings clusterSettings = (ClusterSettings) ReflectionTestUtils
|
||||
.getField(cluster, "settings");
|
||||
List<ServerAddress> 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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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<ServerAddress> 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<ServerAddress> 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<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(2);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
List<MongoCredential> 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,7 @@ 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).createMongoClient(options, null);
|
||||
MongoClientOptions wrapped = client.getMongoClientOptions();
|
||||
assertThat(wrapped.isAlwaysUseMBeans()).isEqualTo(options.isAlwaysUseMBeans());
|
||||
assertThat(wrapped.getConnectionsPerHost())
|
||||
@ -207,27 +111,6 @@ public class MongoPropertiesTests {
|
||||
.isEqualTo(options.getRequiredReplicaSetName());
|
||||
}
|
||||
|
||||
private List<ServerAddress> extractServerAddresses(MongoClient client) {
|
||||
Cluster cluster = (Cluster) ReflectionTestUtils.getField(client, "cluster");
|
||||
ClusterSettings clusterSettings = (ClusterSettings) ReflectionTestUtils
|
||||
.getField(cluster, "settings");
|
||||
List<ServerAddress> 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 {
|
||||
|
@ -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.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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} via {@link MongoProperties}.
|
||||
*
|
||||
* @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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
List<ServerAddress> 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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
List<ServerAddress> 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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
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 = new ReactiveMongoClientFactory(properties).createMongoClient(null,
|
||||
null);
|
||||
List<ServerAddress> allAddresses = extractServerAddresses(client);
|
||||
assertThat(allAddresses).hasSize(2);
|
||||
assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345);
|
||||
assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456);
|
||||
List<MongoCredential> 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");
|
||||
new MongoClientFactory(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");
|
||||
new MongoClientFactory(properties).createMongoClient(null, null);
|
||||
}
|
||||
|
||||
private List<ServerAddress> extractServerAddresses(MongoClient client) {
|
||||
MongoClientSettings settings = client.getSettings();
|
||||
ClusterSettings clusterSettings = settings.getClusterSettings();
|
||||
List<ServerAddress> allAddresses = clusterSettings.getHosts();
|
||||
return allAddresses;
|
||||
}
|
||||
|
||||
private List<MongoCredential> 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);
|
||||
}
|
||||
|
||||
}
|
@ -376,6 +376,11 @@
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
|
@ -34,6 +34,7 @@
|
||||
<module>spring-boot-starter-data-jpa</module>
|
||||
<module>spring-boot-starter-data-ldap</module>
|
||||
<module>spring-boot-starter-data-mongodb</module>
|
||||
<module>spring-boot-starter-data-mongodb-reactive</module>
|
||||
<module>spring-boot-starter-data-neo4j</module>
|
||||
<module>spring-boot-starter-data-redis</module>
|
||||
<module>spring-boot-starter-data-rest</module>
|
||||
|
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starters</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
|
||||
<name>Spring Boot Data MongoDB Reactive Starter</name>
|
||||
<description>Starter for using MongoDB document-oriented database and Spring Data
|
||||
MongoDB Reactive</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-async</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-reactivestreams</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1 @@
|
||||
provides: spring-data-mongodb-reactive
|
Loading…
Reference in New Issue
Block a user