diff --git a/README.adoc b/README.adoc index e2ee15c85..820ace007 100644 --- a/README.adoc +++ b/README.adoc @@ -50,11 +50,11 @@ public class MyService { @Configuration @EnableMongoRepositories -class ApplicationConfig extends AbstractMongoConfiguration { +class ApplicationConfig extends AbstractMongoClientConfiguration { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Override @@ -94,6 +94,120 @@ If you'd rather like the latest snapshots of the upcoming major version, use our ---- +== Upgrading from 2.x + +The 4.0 MongoDB Java Driver does no longer support certain features that have already been deprecated in one of the last minor versions. +Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. + +=== XML Namespace + +.Changed XML Namespace Elements and Attributes: +|=== +Element / Attribute | 2.x | 3.x + +| `` +| Used to create a `com.mongodb.MongoClient` +| Now exposes a `com.mongodb.client.MongoClient` + +| `` +| Was a comma delimited list of replica set members (host/port) +| Now defines the replica set name. + +Use `` instead + +| `` +| NONE, NORMAL, SAFE, FSYNC_SAFE, REPLICAS_SAFE, MAJORITY +| W1, W2, W3, UNAKNOWLEDGED, AKNOWLEDGED, JOURNALED, MAJORITY +|=== + +.Removed XML Namespace Elements and Attributes: +|=== +Element / Attribute | Replacement in 3.x | Comment + +| `` +| `` +| Referencing a `com.mongodb.client.MongoClient`. + +| `` +| `` +| Single authentication data instead of list. + +| `` +| `` +| See `com.mongodb.MongoClientSettings` for details. +|=== + +.New XML Namespace Elements and Attributes: +|=== +Element | Comment + +| `` +| Replacement for `` + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Namespace element for `com.mongodb.MongoClientSettings`. + +|=== + +=== Java Configuration + +.Java API changes +|=== +Type | Comment + +| `MongoClientFactoryBean` +| Creates `com.mongodb.client.MongoClient` instead of `com.mongodb.MongoClient` + +Uses `MongoClientSettings` instead of `MongoClientOptions`. + +| `MongoDataIntegrityViolationException` +| Uses `WriteConcernResult` instead of `WriteResult`. + +| `BulkOperationException` +| Uses `MongoBulkWriteException` and `com.mongodb.bulk.BulkWriteError` instead of `BulkWriteException` and `com.mongodb.BulkWriteError` + +| `ReactiveMongoClientFactoryBean` +| Uses `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` + +| `ReactiveMongoClientSettingsFactoryBean` +| Now produces `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` +|=== + +.Removed Java API: +|=== +2.x | Replacement in 3.x | Comment + +| `MongoClientOptionsFactoryBean` +| `MongoClientSettingsFactoryBean` +| Creating a `com.mongodb.MongoClientSettings`. + +| `AbstractMongoConfiguration` +| `AbstractMongoClientConfiguration` + +(Available since 2.1) +| Using `com.mongodb.client.MongoClient`. + +| `MongoDbFactory#getLegacyDb()` +| - +| - + +| `SimpleMongoDbFactory` +| `SimpleMongoClientDbFactory` + +(Available since 2.1) +| + +| `MapReduceOptions#getOutputType()` +| `MapReduceOptions#getMapReduceAction()` +| Returns `MapReduceAction` instead of `MapReduceCommand.OutputType`. + +| `Meta\|Query` maxScan & snapshot +| +| +|=== + == Getting Help Having trouble with Spring Data? We’d love to help! diff --git a/pom.xml b/pom.xml index 7d73b4d2d..86fbb52cd 100644 --- a/pom.xml +++ b/pom.xml @@ -27,8 +27,8 @@ multi spring-data-mongodb 2.3.0.BUILD-SNAPSHOT - 3.12.0 - 1.13.0 + 4.0.0-SNAPSHOT + ${mongo} 1.19 @@ -127,7 +127,7 @@ org.mongodb - mongo-java-driver + mongodb-driver-core ${mongo} @@ -137,6 +137,12 @@ spring-libs-snapshot https://repo.spring.io/libs-snapshot + + sonatype-libs-snapshot + https://oss.sonatype.org/content/repositories/snapshots + false + true + diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 95beb40e3..04cab785a 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -65,6 +65,12 @@ querydsl-mongodb ${querydsl} true + + + org.mongodb + mongo-java-driver + + @@ -82,28 +88,19 @@ + org.mongodb - mongodb-driver-reactivestreams - ${mongo.reactivestreams} + mongodb-driver-sync + ${mongo} true org.mongodb - mongodb-driver-async - ${mongo} + mongodb-driver-reactivestreams + ${mongo.reactivestreams} true - - - org.mongodb - mongodb-driver-core - - - org.mongodb - bson - - diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java index 4435f4d4e..eee31a1e6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/BulkOperationException.java @@ -19,9 +19,9 @@ import java.util.List; import org.springframework.dao.DataAccessException; -import com.mongodb.BulkWriteError; -import com.mongodb.BulkWriteException; -import com.mongodb.BulkWriteResult; +import com.mongodb.MongoBulkWriteException; +import com.mongodb.bulk.BulkWriteError; +import com.mongodb.bulk.BulkWriteResult; /** * Is thrown when errors occur during bulk operations. @@ -38,12 +38,12 @@ public class BulkOperationException extends DataAccessException { private final BulkWriteResult result; /** - * Creates a new {@link BulkOperationException} with the given message and source {@link BulkWriteException}. + * Creates a new {@link BulkOperationException} with the given message and source {@link MongoBulkWriteException}. * * @param message must not be {@literal null}. * @param source must not be {@literal null}. */ - public BulkOperationException(String message, BulkWriteException source) { + public BulkOperationException(String message, MongoBulkWriteException source) { super(message, source); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java index 6e3faac9b..bd5df0668 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseUtils.java @@ -105,17 +105,17 @@ public class MongoDatabaseUtils { Assert.notNull(factory, "Factory must not be null!"); if (!TransactionSynchronizationManager.isSynchronizationActive()) { - return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb(); + return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } ClientSession session = doGetSession(factory, sessionSynchronization); if (session == null) { - return StringUtils.hasText(dbName) ? factory.getDb(dbName) : factory.getDb(); + return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase(); } MongoDbFactory factoryToUse = factory.withSession(session); - return StringUtils.hasText(dbName) ? factoryToUse.getDb(dbName) : factoryToUse.getDb(); + return StringUtils.hasText(dbName) ? factoryToUse.getMongoDatabase(dbName) : factoryToUse.getMongoDatabase(); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 7ad7d8f81..116d3b1f1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -21,7 +21,6 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.core.MongoExceptionTranslator; import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoDatabase; @@ -39,17 +38,40 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi * * @return * @throws DataAccessException + * @deprecated since 3.0. Use {@link #getMongoDatabase()} instead. */ - MongoDatabase getDb() throws DataAccessException; + @Deprecated + default MongoDatabase getDb() throws DataAccessException { + return getMongoDatabase(); + } /** - * Creates a {@link DB} instance to access the database with the given name. + * Obtain a {@link MongoDatabase} from the underlying factory. + * + * @return never {@literal null}. + * @throws DataAccessException + */ + MongoDatabase getMongoDatabase() throws DataAccessException; + + /** + * Creates a {@link MongoDatabase} instance to access the database with the given name. * * @param dbName must not be {@literal null} or empty. * @return * @throws DataAccessException + * @deprecated since 3.0. Use {@link #getMongoDatabase(String)} instead. */ - MongoDatabase getDb(String dbName) throws DataAccessException; + @Deprecated + default MongoDatabase getDb(String dbName) throws DataAccessException { + return getMongoDatabase(dbName); + } + + /** + * @param dbName + * @return never {@literal null}. + * @throws DataAccessException + */ + MongoDatabase getMongoDatabase(String dbName) throws DataAccessException; /** * Exposes a shared {@link MongoExceptionTranslator}. @@ -58,16 +80,6 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi */ PersistenceExceptionTranslator getExceptionTranslator(); - /** - * Get the legacy database entry point. Please consider {@link #getDb()} instead. - * - * @return - * @deprecated since 2.1, use {@link #getDb()}. This method will be removed with a future version as it works only - * with the legacy MongoDB driver. - */ - @Deprecated - DB getLegacyDb(); - /** * Get the underlying {@link CodecRegistry} used by the MongoDB Java driver. * @@ -75,7 +87,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi */ @Override default CodecRegistry getCodecRegistry() { - return getDb().getCodecRegistry(); + return getMongoDatabase().getCodecRegistry(); } /** diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java index 80fc02eea..d4f333a04 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoTransactionManager.java @@ -45,7 +45,7 @@ import com.mongodb.client.ClientSession; * commit} or {@link ClientSession#abortTransaction() abort} a transaction. *

* Application code is required to retrieve the {@link com.mongodb.client.MongoDatabase} via - * {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getDb()} call. + * {@link MongoDatabaseUtils#getDatabase(MongoDbFactory)} instead of a standard {@link MongoDbFactory#getMongoDatabase()} call. * Spring classes such as {@link org.springframework.data.mongodb.core.MongoTemplate} use this strategy implicitly. *

* By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. One may override diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java index 6627cbb04..cb04fe7be 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java @@ -20,7 +20,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -35,7 +34,6 @@ import com.mongodb.client.MongoClient; * @author Christoph Strobl * @since 2.1 * @see MongoConfigurationSupport - * @see AbstractMongoConfiguration */ @Configuration public abstract class AbstractMongoClientConfiguration extends MongoConfigurationSupport { @@ -59,8 +57,8 @@ public abstract class AbstractMongoClientConfiguration extends MongoConfiguratio } /** - * Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient} - * instance configured in {@link #mongoClient()}. + * Creates a {@link org.springframework.data.mongodb.core.SimpleMongoDbFactory;} to be used by the + * {@link MongoTemplate}. Will use the {@link MongoClient} instance configured in {@link #mongoClient()}. * * @see #mongoClient() * @see #mongoTemplate() diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java deleted file mode 100644 index a5eadefd0..000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2011-2020 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 - * - * https://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.data.mongodb.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; -import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.lang.Nullable; - -import com.mongodb.MongoClient; - -/** - * Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.MongoClient}. - *

- * INFO:In case you want to use {@link com.mongodb.client.MongoClients} for configuration please refer - * to {@link AbstractMongoClientConfiguration}. - * - * @author Mark Pollack - * @author Oliver Gierke - * @author Thomas Darimont - * @author Ryan Tenney - * @author Christoph Strobl - * @author Mark Paluch - * @see MongoConfigurationSupport - * @see AbstractMongoClientConfiguration - * @deprecated since 2.2 in favor of {@link AbstractMongoClientConfiguration}. - */ -@Configuration -@Deprecated -public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport { - - /** - * Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a - * {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}. - * - * @return - */ - public abstract MongoClient mongoClient(); - - /** - * Creates a {@link MongoTemplate}. - * - * @return - */ - @Bean - public MongoTemplate mongoTemplate() throws Exception { - return new MongoTemplate(mongoDbFactory(), mappingMongoConverter()); - } - - /** - * Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link MongoClient} - * instance configured in {@link #mongoClient()}. - * - * @see #mongoClient() - * @see #mongoTemplate() - * @return - */ - @Bean - public MongoDbFactory mongoDbFactory() { - return new SimpleMongoDbFactory(mongoClient(), getDatabaseName()); - } - - /** - * Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration - * class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending - * {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is - * overridden to implement alternate behavior. - * - * @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for - * entities. - * @deprecated use {@link #getMappingBasePackages()} instead. - */ - @Deprecated - @Nullable - protected String getMappingBasePackage() { - - Package mappingBasePackage = getClass().getPackage(); - return mappingBasePackage == null ? null : mappingBasePackage.getName(); - } - - /** - * Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and - * {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied. - * - * @see #customConversions() - * @see #mongoMappingContext() - * @see #mongoDbFactory() - * @return - * @throws Exception - */ - @Bean - public MappingMongoConverter mappingMongoConverter() throws Exception { - - DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); - MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext()); - converter.setCustomConversions(customConversions()); - converter.setCodecRegistryProvider(mongoDbFactory()); - - return converter; - } - -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java new file mode 100644 index 000000000..3fd9017ef --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ConnectionStringPropertyEditor.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.config; + +import java.beans.PropertyEditorSupport; + +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import com.mongodb.ConnectionString; + +/** + * Parse a {@link String} to a {@link com.mongodb.ConnectionString}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ConnectionStringPropertyEditor extends PropertyEditorSupport { + + /* + * (non-Javadoc) + * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String) + */ + @Override + public void setAsText(@Nullable String connectionString) { + + if (!StringUtils.hasText(connectionString)) { + return; + } + + setValue(new ConnectionString(connectionString)); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java index 8aa0a0488..b6e13d856 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoClientParser.java @@ -50,10 +50,11 @@ public class MongoClientParser implements BeanDefinitionParser { ParsingUtils.setPropertyValue(builder, element, "port", "port"); ParsingUtils.setPropertyValue(builder, element, "host", "host"); - ParsingUtils.setPropertyValue(builder, element, "credentials", "credentials"); + ParsingUtils.setPropertyValue(builder, element, "credential", "credential"); + ParsingUtils.setPropertyValue(builder, element, "replica-set", "replicaSet"); + ParsingUtils.setPropertyValue(builder, element, "connection-string", "connectionString"); - MongoParsingUtils.parseMongoClientOptions(element, builder); - MongoParsingUtils.parseReplicaSet(element, builder); + MongoParsingUtils.parseMongoClientSettings(element, builder); String defaultedId = StringUtils.hasText(id) ? id : BeanNames.MONGO_BEAN_NAME; @@ -62,20 +63,28 @@ public class MongoClientParser implements BeanDefinitionParser { BeanComponentDefinition mongoComponent = helper.getComponent(builder, defaultedId); parserContext.registerBeanComponent(mongoComponent); - BeanComponentDefinition serverAddressPropertyEditor = helper.getComponent(MongoParsingUtils - .getServerAddressPropertyEditorBuilder()); + BeanComponentDefinition connectionStringPropertyEditor = helper + .getComponent(MongoParsingUtils.getConnectionStringPropertyEditorBuilder()); + parserContext.registerBeanComponent(connectionStringPropertyEditor); + + BeanComponentDefinition serverAddressPropertyEditor = helper + .getComponent(MongoParsingUtils.getServerAddressPropertyEditorBuilder()); parserContext.registerBeanComponent(serverAddressPropertyEditor); - BeanComponentDefinition writeConcernEditor = helper.getComponent(MongoParsingUtils - .getWriteConcernPropertyEditorBuilder()); + BeanComponentDefinition writeConcernEditor = helper + .getComponent(MongoParsingUtils.getWriteConcernPropertyEditorBuilder()); parserContext.registerBeanComponent(writeConcernEditor); - BeanComponentDefinition readPreferenceEditor = helper.getComponent(MongoParsingUtils - .getReadPreferencePropertyEditorBuilder()); + BeanComponentDefinition readConcernEditor = helper + .getComponent(MongoParsingUtils.getReadConcernPropertyEditorBuilder()); + parserContext.registerBeanComponent(readConcernEditor); + + BeanComponentDefinition readPreferenceEditor = helper + .getComponent(MongoParsingUtils.getReadPreferencePropertyEditorBuilder()); parserContext.registerBeanComponent(readPreferenceEditor); - BeanComponentDefinition credentialsEditor = helper.getComponent(MongoParsingUtils - .getMongoCredentialPropertyEditor()); + BeanComponentDefinition credentialsEditor = helper + .getComponent(MongoParsingUtils.getMongoCredentialPropertyEditor()); parserContext.registerBeanComponent(credentialsEditor); parserContext.popAndRegisterContainingComponent(); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java index 272b4f163..677561c0d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java @@ -32,14 +32,12 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.data.config.BeanComponentDefinitionBuilder; import org.springframework.data.mongodb.core.MongoClientFactoryBean; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import org.w3c.dom.Element; -import com.mongodb.Mongo; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoURI; +import com.mongodb.ConnectionString; /** * {@link BeanDefinitionParser} to parse {@code db-factory} elements into {@link BeanDefinition}s. @@ -84,10 +82,11 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { // Common setup - BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class); + BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder + .genericBeanDefinition(SimpleMongoClientDbFactory.class); setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern"); - BeanDefinition mongoUri = getMongoUri(element, parserContext); + BeanDefinition mongoUri = getConnectionString(element, parserContext); if (mongoUri != null) { @@ -97,7 +96,8 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { BeanComponentDefinitionBuilder helper = new BeanComponentDefinitionBuilder(element, parserContext); - String mongoRef = element.getAttribute("mongo-ref"); + String mongoRef = element.getAttribute("mongo-client-ref"); + String dbname = element.getAttribute("dbname"); // Defaulting @@ -119,8 +119,8 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { } /** - * Registers a default {@link BeanDefinition} of a {@link Mongo} instance and returns the name under which the - * {@link Mongo} instance was registered under. + * Registers a default {@link BeanDefinition} of a {@link com.mongodb.client.MongoClient} instance and returns the + * name under which the {@link com.mongodb.client.MongoClient} instance was registered under. * * @param element must not be {@literal null}. * @param parserContext must not be {@literal null}. @@ -136,8 +136,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { } /** - * Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured - * attributes.
+ * Creates a {@link BeanDefinition} for a {@link ConnectionString} depending on configured attributes.
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except * {@literal write-concern} and/or {@literal id}. * @@ -146,11 +145,19 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { * @return {@literal null} in case no client-/uri defined. */ @Nullable - private BeanDefinition getMongoUri(Element element, ParserContext parserContext) { + private BeanDefinition getConnectionString(Element element, ParserContext parserContext) { - boolean hasClientUri = element.hasAttribute("client-uri"); + String type = null; - if (!hasClientUri && !element.hasAttribute("uri")) { + if (element.hasAttribute("client-uri")) { + type = "client-uri"; + } else if (element.hasAttribute("connection-string")) { + type = "connection-string"; + } else if (element.hasAttribute("uri")) { + type = "uri"; + } + + if (!StringUtils.hasText(type)) { return null; } @@ -164,16 +171,12 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser { if (element.getAttributes().getLength() > allowedAttributesCount) { - parserContext.getReaderContext().error( - "Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!", + parserContext.getReaderContext().error("Configure either MongoDB " + type + " or details individually!", parserContext.extractSource(element)); } - Class type = MongoClientURI.class; - String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri"); - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type); - builder.addConstructorArgValue(uri); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ConnectionString.class); + builder.addConstructorArgValue(element.getAttribute(type)); return builder.getBeanDefinition(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index aa85041d9..96d6a2320 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.config.CustomEditorConfigurer; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.data.mongodb.core.MongoClientOptionsFactoryBean; +import org.springframework.data.mongodb.core.MongoClientSettingsFactoryBean; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -43,60 +43,77 @@ abstract class MongoParsingUtils { private MongoParsingUtils() {} /** - * Parses the mongo replica-set element. - * - * @param parserContext the parser context - * @param element the mongo element - * @param mongoBuilder the bean definition builder to populate - * @return - */ - static void parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) { - setPropertyValue(mongoBuilder, element, "replica-set", "replicaSetSeeds"); - } - - /** - * Parses the {@code mongo:client-options} sub-element. Populates the given attribute factory with the proper + * Parses the {@code mongo:client-settings} sub-element. Populates the given attribute factory with the proper * attributes. - * - * @param element must not be {@literal null}. - * @param mongoClientBuilder must not be {@literal null}. + * + * @param element + * @param mongoClientBuilder * @return - * @since 1.7 + * @since 3.0 */ - public static boolean parseMongoClientOptions(Element element, BeanDefinitionBuilder mongoClientBuilder) { + public static boolean parseMongoClientSettings(Element element, BeanDefinitionBuilder mongoClientBuilder) { - Element optionsElement = DomUtils.getChildElementByTagName(element, "client-options"); - - if (optionsElement == null) { + Element settingsElement = DomUtils.getChildElementByTagName(element, "client-settings"); + if (settingsElement == null) { return false; } BeanDefinitionBuilder clientOptionsDefBuilder = BeanDefinitionBuilder - .genericBeanDefinition(MongoClientOptionsFactoryBean.class); + .genericBeanDefinition(MongoClientSettingsFactoryBean.class); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "description", "description"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-connections-per-host", "minConnectionsPerHost"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "connections-per-host", "connectionsPerHost"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "threads-allowed-to-block-for-connection-multiplier", - "threadsAllowedToBlockForConnectionMultiplier"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-wait-time", "maxWaitTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-idle-time", "maxConnectionIdleTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "max-connection-life-time", "maxConnectionLifeTime"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "connect-timeout", "connectTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-timeout", "socketTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "socket-keep-alive", "socketKeepAlive"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "read-preference", "readPreference"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "write-concern", "writeConcern"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-frequency", "heartbeatFrequency"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "min-heartbeat-frequency", "minHeartbeatFrequency"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-connect-timeout", "heartbeatConnectTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl"); - setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory"); - setPropertyReference(clientOptionsDefBuilder, optionsElement, "encryption-settings-ref", "autoEncryptionSettings"); - setPropertyValue(clientOptionsDefBuilder, optionsElement, "server-selection-timeout", "serverSelectionTimeout"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "application-name", "applicationName"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "read-preference", "readPreference"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "read-concern", "readConcern"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "write-concern", "writeConcern"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-reads", "retryReads"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "retry-writes", "retryWrites"); - mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition()); + // SocketSettings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-connect-timeout", "socketConnectTimeoutMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-read-timeout", "socketReadTimeoutMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-receive-buffer-size", "socketReceiveBufferSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "socket-send-buffer-size", "socketSendBufferSize"); + + // Server Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "server-heartbeat-frequency", + "serverHeartbeatFrequencyMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "server-min-heartbeat-frequency", + "serverMinHeartbeatFrequencyMS"); + + // Cluster Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-srv-host", "clusterSrvHost"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-hosts", "clusterHosts"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-connection-mode", "clusterConnectionMode"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-type", "custerRequiredClusterType"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-local-threshold", "clusterLocalThresholdMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "cluster-server-selection-timeout", + "clusterServerSelectionTimeoutMS"); + + // Connection Pool Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-size", "poolMaxSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-min-size", "poolMinSize"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-wait-time", "poolMaxWaitTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-connection-life-time", + "poolMaxConnectionLifeTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-max-connection-idle-time", + "poolMaxConnectionIdleTimeMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-maintenance-initial-delay", + "poolMaintenanceInitialDelayMS"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "connection-pool-maintenance-frequency", + "poolMaintenanceFrequencyMS"); + + // SSL Settings + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-enabled", "sslEnabled"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-invalid-host-name-allowed", + "sslInvalidHostNameAllowed"); + setPropertyValue(clientOptionsDefBuilder, settingsElement, "ssl-provider", "sslProvider"); + + // Field level encryption + setPropertyReference(clientOptionsDefBuilder, settingsElement, "encryption-settings-ref", "autoEncryptionSettings"); + + // and the rest + + mongoClientBuilder.addPropertyValue("mongoClientSettings", clientOptionsDefBuilder.getBeanDefinition()); return true; } @@ -118,6 +135,24 @@ abstract class MongoParsingUtils { return builder; } + /** + * Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a + * {@link ReadConcernPropertyEditor}. + * + * @return + * @since 3.0 + */ + static BeanDefinitionBuilder getReadConcernPropertyEditorBuilder() { + + Map> customEditors = new ManagedMap<>(); + customEditors.put("com.mongodb.ReadConcern", ReadConcernPropertyEditor.class); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); + builder.addPropertyValue("customEditors", customEditors); + + return builder; + } + /** * One should only register one bean definition but want to have the convenience of using * AbstractSingleBeanDefinitionParser but have the side effect of registering a 'default' property editor with the @@ -125,7 +160,7 @@ abstract class MongoParsingUtils { */ static BeanDefinitionBuilder getServerAddressPropertyEditorBuilder() { - Map customEditors = new ManagedMap(); + Map customEditors = new ManagedMap<>(); customEditors.put("com.mongodb.ServerAddress[]", "org.springframework.data.mongodb.config.ServerAddressPropertyEditor"); @@ -143,7 +178,7 @@ abstract class MongoParsingUtils { */ static BeanDefinitionBuilder getReadPreferencePropertyEditorBuilder() { - Map> customEditors = new ManagedMap>(); + Map> customEditors = new ManagedMap<>(); customEditors.put("com.mongodb.ReadPreference", ReadPreferencePropertyEditor.class); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); @@ -169,4 +204,23 @@ abstract class MongoParsingUtils { return builder; } + + /** + * Returns the {@link BeanDefinitionBuilder} to build a {@link BeanDefinition} for a + * {@link ConnectionStringPropertyEditor}. + * + * @return + * @since 3.0 + */ + static BeanDefinitionBuilder getConnectionStringPropertyEditorBuilder() { + + Map> customEditors = new ManagedMap<>(); + customEditors.put("com.mongodb.ConnectionString", ConnectionStringPropertyEditor.class); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); + builder.addPropertyValue("customEditors", customEditors); + + return builder; + } + } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java new file mode 100644 index 000000000..ed5d73d6e --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/ReadConcernPropertyEditor.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.config; + +import java.beans.PropertyEditorSupport; + +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import com.mongodb.ReadConcern; +import com.mongodb.ReadConcernLevel; + +/** + * Parse a {@link String} to a {@link ReadConcern}. If it is a well know {@link String} as identified by the + * {@link ReadConcernLevel#fromString(String)}. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ReadConcernPropertyEditor extends PropertyEditorSupport { + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext) + */ + @Override + public void setAsText(@Nullable String readConcernString) { + + if (!StringUtils.hasText(readConcernString)) { + return; + } + + setValue(new ReadConcern(ReadConcernLevel.fromString(readConcernString))); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java index 0ce3f0001..e1b1531e1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java @@ -34,7 +34,7 @@ import com.mongodb.WriteConcern; public class WriteConcernPropertyEditor extends PropertyEditorSupport { /** - * Parse a string to a List + * Parse a string to a {@link WriteConcern}. */ @Override public void setAsText(@Nullable String writeConcernString) { @@ -51,6 +51,5 @@ public class WriteConcernPropertyEditor extends PropertyEditorSupport { // pass on the string to the constructor setValue(new WriteConcern(writeConcernString)); } - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java index 8a92d39e5..e19836892 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoAdmin.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.util.Assert; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** @@ -34,24 +34,13 @@ import com.mongodb.client.MongoDatabase; @ManagedResource(description = "Mongo Admin Operations") public class MongoAdmin implements MongoAdminOperations { - private final Object mongoClient; - - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link MongoAdmin#MongoAdmin(com.mongodb.client.MongoClient)}. - */ - @Deprecated - public MongoAdmin(MongoClient mongoClient) { - - Assert.notNull(mongoClient, "MongoClient must not be null!"); - this.mongoClient = mongoClient; - } + private final MongoClient mongoClient; /** * @param client the underlying {@link com.mongodb.client.MongoClient} used for data access. * @since 2.2 */ - public MongoAdmin(com.mongodb.client.MongoClient client) { + public MongoAdmin(MongoClient client) { Assert.notNull(client, "Client must not be null!"); this.mongoClient = client; @@ -88,11 +77,6 @@ public class MongoAdmin implements MongoAdminOperations { } MongoDatabase getDB(String databaseName) { - - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getDatabase(databaseName); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getDatabase(databaseName); + return mongoClient.getDatabase(databaseName); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java index 3f207eba0..e103fd37f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientFactoryBean.java @@ -16,70 +16,70 @@ package org.springframework.data.mongodb.core; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.dao.DataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +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.event.ClusterListener; /** * Convenient factory for configuring MongoDB. * * @author Christoph Strobl * @author Mark Paluch - * @since 1.7 - * @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean} at - * this time. However moving forward the {@link org.springframework.beans.factory.FactoryBean} will be - * suitable to provide instances of {@link com.mongodb.client.MongoClient}. */ -@Deprecated public class MongoClientFactoryBean extends AbstractFactoryBean implements PersistenceExceptionTranslator { private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator(); - private @Nullable MongoClientOptions mongoClientOptions; + private @Nullable MongoClientSettings mongoClientSettings; private @Nullable String host; private @Nullable Integer port; - private List replicaSetSeeds = Collections.emptyList(); - private List credentials = Collections.emptyList(); + private @Nullable List credential = null; + private @Nullable ConnectionString connectionString; + private @Nullable String replicaSet = null; private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_EXCEPTION_TRANSLATOR; /** - * Set the {@link MongoClientOptions} to be used when creating {@link MongoClient}. + * Set the {@link MongoClientSettings} to be used when creating {@link MongoClient}. * * @param mongoClientOptions */ - public void setMongoClientOptions(@Nullable MongoClientOptions mongoClientOptions) { - this.mongoClientOptions = mongoClientOptions; + public void setMongoClientSettings(@Nullable MongoClientSettings mongoClientOptions) { + this.mongoClientSettings = mongoClientOptions; } /** * Set the list of credentials to be used when creating {@link MongoClient}. * - * @param credentials can be {@literal null}. + * @param credential can be {@literal null}. */ - public void setCredentials(@Nullable MongoCredential[] credentials) { - this.credentials = filterNonNullElementsAsList(credentials); - } - - /** - * Set the list of {@link ServerAddress} to build up a replica set for. - * - * @param replicaSetSeeds can be {@literal null}. - */ - public void setReplicaSetSeeds(@Nullable ServerAddress[] replicaSetSeeds) { - this.replicaSetSeeds = filterNonNullElementsAsList(replicaSetSeeds); + public void setCredential(@Nullable MongoCredential[] credential) { + this.credential = Arrays.asList(credential); } /** @@ -100,6 +100,14 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp this.port = port; } + public void setConnectionString(@Nullable ConnectionString connectionString) { + this.connectionString = connectionString; + } + + public void setReplicaSet(@Nullable String replicaSet) { + this.replicaSet = replicaSet; + } + /** * Configures the {@link PersistenceExceptionTranslator} to use. * @@ -132,12 +140,193 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp */ @Override protected MongoClient createInstance() throws Exception { + return createMongoClient(computeClientSetting()); + } - if (mongoClientOptions == null) { - mongoClientOptions = MongoClientOptions.builder().build(); + /** + * Create {@link MongoClientSettings} based on configuration and priority (lower is better).
+ * 1. {@link MongoClientFactoryBean#mongoClientSettings}
+ * 2. {@link MongoClientFactoryBean#connectionString}
+ * 3. default {@link MongoClientSettings} + * + * @since 3.0 + */ + protected MongoClientSettings computeClientSetting() { + + if (connectionString != null && (StringUtils.hasText(host) || port != null)) { + throw new IllegalStateException("ConnectionString and host/port configuration exclude one another!"); } - return createMongoClient(); + ConnectionString connectionString = this.connectionString != null ? this.connectionString + : new ConnectionString(String.format("mongodb://%s:%s", getOrDefault(host, ServerAddress.defaultHost()), + getOrDefault(port, "" + ServerAddress.defaultPort()))); + + Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString); + + if (mongoClientSettings != null) { + + MongoClientSettings defaultSettings = MongoClientSettings.builder().build(); + + SslSettings sslSettings = mongoClientSettings.getSslSettings(); + ClusterSettings clusterSettings = mongoClientSettings.getClusterSettings(); + ConnectionPoolSettings connectionPoolSettings = mongoClientSettings.getConnectionPoolSettings(); + SocketSettings socketSettings = mongoClientSettings.getSocketSettings(); + ServerSettings serverSettings = mongoClientSettings.getServerSettings(); + + builder = builder // + .applicationName(computeSettingsValue(defaultSettings.getApplicationName(), + mongoClientSettings.getApplicationName(), connectionString.getApplicationName())) // + .applyToSslSettings(settings -> { + + applySettings(settings::enabled, computeSettingsValue(SslSettings::isEnabled, + defaultSettings.getSslSettings(), sslSettings, connectionString.getSslEnabled())); + applySettings(settings::invalidHostNameAllowed, (computeSettingsValue(SslSettings::isInvalidHostNameAllowed, + defaultSettings.getSslSettings(), sslSettings, connectionString.getSslInvalidHostnameAllowed()))); + settings.context(sslSettings.getContext()); + }).applyToClusterSettings(settings -> { + + applySettings(settings::hosts, + computeSettingsValue(ClusterSettings::getHosts, defaultSettings.getClusterSettings(), clusterSettings, + connectionString.getHosts().stream().map(ServerAddress::new).collect(Collectors.toList()))); + + applySettings(settings::requiredReplicaSetName, + computeSettingsValue(ClusterSettings::getRequiredReplicaSetName, defaultSettings.getClusterSettings(), + clusterSettings, connectionString.getRequiredReplicaSetName())); + + applySettings(settings::srvHost, computeSettingsValue(ClusterSettings::getSrvHost, + defaultSettings.getClusterSettings(), clusterSettings, null)); + + applySettings(settings::mode, computeSettingsValue(ClusterSettings::getMode, + defaultSettings.getClusterSettings(), clusterSettings, null)); + + applySettings(it -> settings.localThreshold(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ClusterSettings it) -> it.getLocalThreshold(TimeUnit.MILLISECONDS), + defaultSettings.getClusterSettings(), clusterSettings, connectionString.getLocalThreshold())); + + applySettings(settings::requiredClusterType, computeSettingsValue(ClusterSettings::getRequiredClusterType, + defaultSettings.getClusterSettings(), clusterSettings, null)); + applySettings(it -> settings.serverSelectionTimeout(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ClusterSettings it) -> it.getServerSelectionTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getClusterSettings(), clusterSettings, + connectionString.getServerSelectionTimeout())); + + applySettings(settings::serverSelector, computeSettingsValue(ClusterSettings::getServerSelector, + defaultSettings.getClusterSettings(), clusterSettings, null)); + List clusterListeners = computeSettingsValue(ClusterSettings::getClusterListeners, + defaultSettings.getClusterSettings(), clusterSettings, null); + if (clusterListeners != null) { + clusterListeners.forEach(settings::addClusterListener); + } + }) // + .applyToConnectionPoolSettings(settings -> { + + applySettings(it -> settings.maintenanceFrequency(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaintenanceFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); + + applySettings(it -> settings.maxConnectionIdleTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxConnectionIdleTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxConnectionIdleTime())); + + applySettings(it -> settings.maxConnectionLifeTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxConnectionLifeTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxConnectionLifeTime())); + + applySettings(it -> settings.maxWaitTime(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ConnectionPoolSettings it) -> it.getMaxWaitTime(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, + connectionString.getMaxWaitTime())); + + applySettings(it -> settings.maintenanceInitialDelay(it.longValue(), TimeUnit.MILLISECONDS), + computeSettingsValue( + (ConnectionPoolSettings it) -> it.getMaintenanceInitialDelay(TimeUnit.MILLISECONDS), + defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); + + applySettings(settings::minSize, + computeSettingsValue(ConnectionPoolSettings::getMinSize, defaultSettings.getConnectionPoolSettings(), + connectionPoolSettings, connectionString.getMinConnectionPoolSize())); + applySettings(settings::maxSize, + computeSettingsValue(ConnectionPoolSettings::getMaxSize, defaultSettings.getConnectionPoolSettings(), + connectionPoolSettings, connectionString.getMaxConnectionPoolSize())); + }) // + .applyToSocketSettings(settings -> { + + applySettings(it -> settings.connectTimeout(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((SocketSettings it) -> it.getConnectTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getSocketSettings(), socketSettings, connectionString.getConnectTimeout())); + + applySettings(it -> settings.readTimeout(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((SocketSettings it) -> it.getReadTimeout(TimeUnit.MILLISECONDS), + defaultSettings.getSocketSettings(), socketSettings, connectionString.getSocketTimeout())); + applySettings(settings::receiveBufferSize, computeSettingsValue(SocketSettings::getReceiveBufferSize, + defaultSettings.getSocketSettings(), socketSettings, null)); + applySettings(settings::sendBufferSize, computeSettingsValue(SocketSettings::getSendBufferSize, + defaultSettings.getSocketSettings(), socketSettings, null)); + }) // + .applyToServerSettings(settings -> { + + applySettings(it -> settings.minHeartbeatFrequency(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ServerSettings it) -> it.getMinHeartbeatFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getServerSettings(), serverSettings, null)); + + applySettings(it -> settings.heartbeatFrequency(it.intValue(), TimeUnit.MILLISECONDS), + computeSettingsValue((ServerSettings it) -> it.getHeartbeatFrequency(TimeUnit.MILLISECONDS), + defaultSettings.getServerSettings(), serverSettings, connectionString.getHeartbeatFrequency())); + settings.applySettings(serverSettings); + }) // + .autoEncryptionSettings(mongoClientSettings.getAutoEncryptionSettings()) // + .codecRegistry(mongoClientSettings.getCodecRegistry()); // + + applySettings(builder::readConcern, computeSettingsValue(defaultSettings.getReadConcern(), + mongoClientSettings.getReadConcern(), connectionString.getReadConcern())); + applySettings(builder::writeConcern, computeSettingsValue(defaultSettings.getWriteConcern(), + mongoClientSettings.getWriteConcern(), connectionString.getWriteConcern())); + applySettings(builder::readPreference, computeSettingsValue(defaultSettings.getReadPreference(), + mongoClientSettings.getReadPreference(), connectionString.getReadPreference())); + applySettings(builder::retryReads, computeSettingsValue(defaultSettings.getRetryReads(), + mongoClientSettings.getRetryReads(), connectionString.getRetryReads())); + applySettings(builder::retryWrites, computeSettingsValue(defaultSettings.getRetryWrites(), + mongoClientSettings.getRetryWrites(), connectionString.getRetryWritesValue())); + } + + if (!CollectionUtils.isEmpty(credential)) { + builder = builder.credential(credential.iterator().next()); + } + + if (StringUtils.hasText(replicaSet)) { + builder.applyToClusterSettings((settings) -> { + settings.requiredReplicaSetName(replicaSet); + }); + } + + return builder.build(); + } + + private void applySettings(Consumer settingsBuilder, @Nullable T value) { + + if (ObjectUtils.isEmpty(value)) { + return; + } + settingsBuilder.accept(value); + } + + private T computeSettingsValue(Function function, S defaultValueHolder, S settingsValueHolder, + @Nullable T connectionStringValue) { + return computeSettingsValue(function.apply(defaultValueHolder), function.apply(settingsValueHolder), + connectionStringValue); + } + + private T computeSettingsValue(T defaultValue, T fromSettings, T fromConnectionString) { + + boolean fromSettingsIsDefault = ObjectUtils.nullSafeEquals(defaultValue, fromSettings); + boolean fromConnectionStringIsDefault = ObjectUtils.nullSafeEquals(defaultValue, fromConnectionString); + + if (!fromSettingsIsDefault) { + return fromSettings; + } + return !fromConnectionStringIsDefault ? fromConnectionString : defaultValue; } /* @@ -152,43 +341,11 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp } } - private MongoClient createMongoClient() throws UnknownHostException { - - if (!CollectionUtils.isEmpty(replicaSetSeeds)) { - return new MongoClient(replicaSetSeeds, credentials, mongoClientOptions); - } - - return new MongoClient(createConfiguredOrDefaultServerAddress(), credentials, mongoClientOptions); + private MongoClient createMongoClient(MongoClientSettings settings) throws UnknownHostException { + return MongoClients.create(settings); } - private ServerAddress createConfiguredOrDefaultServerAddress() throws UnknownHostException { - - ServerAddress defaultAddress = new ServerAddress(); - - return new ServerAddress(StringUtils.hasText(host) ? host : defaultAddress.getHost(), - port != null ? port.intValue() : defaultAddress.getPort()); - } - - /** - * Returns the given array as {@link List} with all {@literal null} elements removed. - * - * @param elements the elements to filter , can be {@literal null}. - * @return a new unmodifiable {@link List#} from the given elements without {@literal null}s. - */ - private static List filterNonNullElementsAsList(@Nullable T[] elements) { - - if (elements == null) { - return Collections.emptyList(); - } - - List candidateElements = new ArrayList(); - - for (T element : elements) { - if (element != null) { - candidateElements.add(element); - } - } - - return Collections.unmodifiableList(candidateElements); + private String getOrDefault(Object value, String defaultValue) { + return !StringUtils.isEmpty(value) ? value.toString() : defaultValue; } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java deleted file mode 100644 index 8b2b552c7..000000000 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBean.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2015-2020 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 - * - * https://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.data.mongodb.core; - -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.data.mongodb.MongoDbFactory; -import org.springframework.lang.Nullable; - -import com.mongodb.AutoEncryptionSettings; -import com.mongodb.DBDecoderFactory; -import com.mongodb.DBEncoderFactory; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; - -/** - * A factory bean for construction of a {@link MongoClientOptions} instance. - * - * @author Christoph Strobl - * @author Oliver Gierke - * @author Mark Paluch - * @since 1.7 - * @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean}. - * However moving forward there will be a dedicated factory bean for {@link com.mongodb.MongoClientSettings} - * replacing {@link MongoClientOptions}. - */ -@Deprecated -public class MongoClientOptionsFactoryBean extends AbstractFactoryBean { - - private static final MongoClientOptions DEFAULT_MONGO_OPTIONS = MongoClientOptions.builder().build(); - - // TODO: Mongo Driver 4 - use application name insetad of description if not available - private @Nullable String description = DEFAULT_MONGO_OPTIONS.getApplicationName(); - private int minConnectionsPerHost = DEFAULT_MONGO_OPTIONS.getMinConnectionsPerHost(); - private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.getConnectionsPerHost(); - private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS - .getThreadsAllowedToBlockForConnectionMultiplier(); - private int maxWaitTime = DEFAULT_MONGO_OPTIONS.getMaxWaitTime(); - private int maxConnectionIdleTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionIdleTime(); - private int maxConnectionLifeTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionLifeTime(); - private int connectTimeout = DEFAULT_MONGO_OPTIONS.getConnectTimeout(); - private int socketTimeout = DEFAULT_MONGO_OPTIONS.getSocketTimeout(); - - // TODO: Mongo Driver 4 - check if available - private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.isSocketKeepAlive(); - private @Nullable ReadPreference readPreference = DEFAULT_MONGO_OPTIONS.getReadPreference(); - private DBDecoderFactory dbDecoderFactory = DEFAULT_MONGO_OPTIONS.getDbDecoderFactory(); - private DBEncoderFactory dbEncoderFactory = DEFAULT_MONGO_OPTIONS.getDbEncoderFactory(); - private @Nullable WriteConcern writeConcern = DEFAULT_MONGO_OPTIONS.getWriteConcern(); - private @Nullable SocketFactory socketFactory = DEFAULT_MONGO_OPTIONS.getSocketFactory(); - private boolean cursorFinalizerEnabled = DEFAULT_MONGO_OPTIONS.isCursorFinalizerEnabled(); - - // TODO: Mongo Driver 4 - remove this option - private boolean alwaysUseMBeans = DEFAULT_MONGO_OPTIONS.isAlwaysUseMBeans(); - private int heartbeatFrequency = DEFAULT_MONGO_OPTIONS.getHeartbeatFrequency(); - private int minHeartbeatFrequency = DEFAULT_MONGO_OPTIONS.getMinHeartbeatFrequency(); - private int heartbeatConnectTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatConnectTimeout(); - private int heartbeatSocketTimeout = DEFAULT_MONGO_OPTIONS.getHeartbeatSocketTimeout(); - private String requiredReplicaSetName = DEFAULT_MONGO_OPTIONS.getRequiredReplicaSetName(); - private int serverSelectionTimeout = DEFAULT_MONGO_OPTIONS.getServerSelectionTimeout(); - - private boolean ssl; - private @Nullable SSLSocketFactory sslSocketFactory; - private @Nullable AutoEncryptionSettings autoEncryptionSettings; - - /** - * Set the {@link MongoClient} description. - * - * @param description - */ - // TODO: Mongo Driver 4 - deprecate that one and add application name - public void setDescription(@Nullable String description) { - this.description = description; - } - - /** - * Set the minimum number of connections per host. - * - * @param minConnectionsPerHost - */ - public void setMinConnectionsPerHost(int minConnectionsPerHost) { - this.minConnectionsPerHost = minConnectionsPerHost; - } - - /** - * Set the number of connections allowed per host. Will block if run out. Default is 10. System property - * {@code MONGO.POOLSIZE} can override - * - * @param connectionsPerHost - */ - public void setConnectionsPerHost(int connectionsPerHost) { - this.connectionsPerHost = connectionsPerHost; - } - - /** - * Set the multiplier for connectionsPerHost for # of threads that can block. Default is 5. If connectionsPerHost is - * 10, and threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an - * exception will be thrown. - * - * @param threadsAllowedToBlockForConnectionMultiplier - */ - public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) { - this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; - } - - /** - * Set the max wait time of a blocking thread for a connection. Default is 12000 ms (2 minutes) - * - * @param maxWaitTime - */ - public void setMaxWaitTime(int maxWaitTime) { - this.maxWaitTime = maxWaitTime; - } - - /** - * The maximum idle time for a pooled connection. - * - * @param maxConnectionIdleTime - */ - public void setMaxConnectionIdleTime(int maxConnectionIdleTime) { - this.maxConnectionIdleTime = maxConnectionIdleTime; - } - - /** - * Set the maximum life time for a pooled connection. - * - * @param maxConnectionLifeTime - */ - public void setMaxConnectionLifeTime(int maxConnectionLifeTime) { - this.maxConnectionLifeTime = maxConnectionLifeTime; - } - - /** - * Set the connect timeout in milliseconds. 0 is default and infinite. - * - * @param connectTimeout - */ - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } - - /** - * Set the socket timeout. 0 is default and infinite. - * - * @param socketTimeout - */ - public void setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - } - - /** - * Set the keep alive flag, controls whether or not to have socket keep alive timeout. Defaults to false. - * - * @param socketKeepAlive - */ - public void setSocketKeepAlive(boolean socketKeepAlive) { - this.socketKeepAlive = socketKeepAlive; - } - - /** - * Set the {@link ReadPreference}. - * - * @param readPreference - */ - public void setReadPreference(@Nullable ReadPreference readPreference) { - this.readPreference = readPreference; - } - - /** - * Set the {@link WriteConcern} that will be the default value used when asking the {@link MongoDbFactory} for a DB - * object. - * - * @param writeConcern - */ - public void setWriteConcern(@Nullable WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * @param socketFactory - */ - public void setSocketFactory(@Nullable SocketFactory socketFactory) { - this.socketFactory = socketFactory; - } - - /** - * Set the frequency that the driver will attempt to determine the current state of each server in the cluster. - * - * @param heartbeatFrequency - */ - public void setHeartbeatFrequency(int heartbeatFrequency) { - this.heartbeatFrequency = heartbeatFrequency; - } - - /** - * In the event that the driver has to frequently re-check a server's availability, it will wait at least this long - * since the previous check to avoid wasted effort. - * - * @param minHeartbeatFrequency - */ - public void setMinHeartbeatFrequency(int minHeartbeatFrequency) { - this.minHeartbeatFrequency = minHeartbeatFrequency; - } - - /** - * Set the connect timeout for connections used for the cluster heartbeat. - * - * @param heartbeatConnectTimeout - */ - public void setHeartbeatConnectTimeout(int heartbeatConnectTimeout) { - this.heartbeatConnectTimeout = heartbeatConnectTimeout; - } - - /** - * Set the socket timeout for connections used for the cluster heartbeat. - * - * @param heartbeatSocketTimeout - */ - public void setHeartbeatSocketTimeout(int heartbeatSocketTimeout) { - this.heartbeatSocketTimeout = heartbeatSocketTimeout; - } - - /** - * Configures the name of the replica set. - * - * @param requiredReplicaSetName - */ - public void setRequiredReplicaSetName(String requiredReplicaSetName) { - this.requiredReplicaSetName = requiredReplicaSetName; - } - - /** - * This controls if the driver should us an SSL connection. Defaults to {@literal false}. - * - * @param ssl - */ - public void setSsl(boolean ssl) { - this.ssl = ssl; - } - - /** - * Set the {@link SSLSocketFactory} to use for the {@literal SSL} connection. If none is configured here, - * {@link SSLSocketFactory#getDefault()} will be used. - * - * @param sslSocketFactory - */ - public void setSslSocketFactory(@Nullable SSLSocketFactory sslSocketFactory) { - - this.sslSocketFactory = sslSocketFactory; - this.ssl = sslSocketFactory != null; - } - - /** - * Set the {@literal server selection timeout} in msec for a 3.x MongoDB Java driver. If not set the default value of - * 30 sec will be used. A value of 0 means that it will timeout immediately if no server is available. A negative - * value means to wait indefinitely. - * - * @param serverSelectionTimeout in msec. - */ - public void setServerSelectionTimeout(int serverSelectionTimeout) { - this.serverSelectionTimeout = serverSelectionTimeout; - } - - /** - * Set the {@link AutoEncryptionSettings} to be used. - * - * @param autoEncryptionSettings can be {@literal null}. - * @since 2.2 - */ - public void setAutoEncryptionSettings(@Nullable AutoEncryptionSettings autoEncryptionSettings) { - this.autoEncryptionSettings = autoEncryptionSettings; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() - */ - @SuppressWarnings("ConstantConditions") - @Override - protected MongoClientOptions createInstance() throws Exception { - - SocketFactory socketFactoryToUse = ssl - ? (sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault()) - : this.socketFactory; - - return MongoClientOptions.builder() // - .alwaysUseMBeans(this.alwaysUseMBeans) // - .connectionsPerHost(this.connectionsPerHost) // - .connectTimeout(connectTimeout) // - .cursorFinalizerEnabled(cursorFinalizerEnabled) // - .dbDecoderFactory(dbDecoderFactory) // - .dbEncoderFactory(dbEncoderFactory) // - .applicationName(description) // TODO: Mongo Driver 4 - use application name if description not available - .heartbeatConnectTimeout(heartbeatConnectTimeout) // - .heartbeatFrequency(heartbeatFrequency) // - .heartbeatSocketTimeout(heartbeatSocketTimeout) // - .maxConnectionIdleTime(maxConnectionIdleTime) // - .maxConnectionLifeTime(maxConnectionLifeTime) // - .maxWaitTime(maxWaitTime) // - .minConnectionsPerHost(minConnectionsPerHost) // - .minHeartbeatFrequency(minHeartbeatFrequency) // - .readPreference(readPreference) // - .requiredReplicaSetName(requiredReplicaSetName) // - .serverSelectionTimeout(serverSelectionTimeout) // - .sslEnabled(ssl) // - .autoEncryptionSettings(autoEncryptionSettings) // - .socketFactory(socketFactoryToUse) // TODO: Mongo Driver 4 - - .socketKeepAlive(socketKeepAlive) // TODO: Mongo Driver 4 - remove if not available - .socketTimeout(socketTimeout) // - .threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier) // - .writeConcern(writeConcern).build(); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.FactoryBean#getObjectType() - */ - public Class getObjectType() { - return MongoClientOptions.class; - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java new file mode 100644 index 000000000..e688433b6 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBean.java @@ -0,0 +1,464 @@ +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.core; + +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLContext; + +import org.bson.codecs.configuration.CodecRegistry; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import com.mongodb.AutoEncryptionSettings; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; +import com.mongodb.ReadConcern; +import com.mongodb.ReadPreference; +import com.mongodb.ServerAddress; +import com.mongodb.WriteConcern; +import com.mongodb.connection.ClusterConnectionMode; +import com.mongodb.connection.ClusterType; +import com.mongodb.connection.StreamFactoryFactory; + +/** + * A factory bean for construction of a {@link MongoClientSettings} instance to be used with a MongoDB driver. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { + + private static final MongoClientSettings DEFAULT_MONGO_SETTINGS = MongoClientSettings.builder().build(); + + private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry(); + private StreamFactoryFactory streamFactoryFactory = DEFAULT_MONGO_SETTINGS.getStreamFactoryFactory(); + + private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference(); + private ReadConcern readConcern = DEFAULT_MONGO_SETTINGS.getReadConcern(); + private @Nullable Boolean retryReads = null; + + private WriteConcern writeConcern = DEFAULT_MONGO_SETTINGS.getWriteConcern(); + private @Nullable Boolean retryWrites = null; + + private @Nullable String applicationName = null; + + // --> Socket Settings + + private Integer socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + .getConnectTimeout(TimeUnit.MILLISECONDS); + private Integer socketReadTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + .getReadTimeout(TimeUnit.MILLISECONDS); + private Integer socketReceiveBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReceiveBufferSize(); + private Integer socketSendBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getSendBufferSize(); + + /** + * @param socketConnectTimeoutMS in msec + * @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(int, TimeUnit) + */ + public void setSocketConnectTimeoutMS(Integer socketConnectTimeoutMS) { + this.socketConnectTimeoutMS = socketConnectTimeoutMS; + } + + /** + * @param socketReadTimeoutMS in msec + * @see com.mongodb.connection.SocketSettings.Builder#readTimeout(int, TimeUnit) + */ + public void setSocketReadTimeoutMS(Integer socketReadTimeoutMS) { + this.socketReadTimeoutMS = socketReadTimeoutMS; + } + + /** + * @param socketReceiveBufferSize + * @see com.mongodb.connection.SocketSettings.Builder#receiveBufferSize(int) + */ + public void setSocketReceiveBufferSize(Integer socketReceiveBufferSize) { + this.socketReceiveBufferSize = socketReceiveBufferSize; + } + + /** + * @param socketSendBufferSize + * @see com.mongodb.connection.SocketSettings.Builder#sendBufferSize(int) + */ + public void setSocketSendBufferSize(Integer socketSendBufferSize) { + this.socketSendBufferSize = socketSendBufferSize; + } + + // --> Server Settings + + private Long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + .getHeartbeatFrequency(TimeUnit.MILLISECONDS); + private Long serverMinHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + .getMinHeartbeatFrequency(TimeUnit.MILLISECONDS); + + /** + * @param serverHeartbeatFrequencyMS in msec + * @see com.mongodb.connection.ServerSettings.Builder#heartbeatFrequency(long, TimeUnit) + */ + public void setServerHeartbeatFrequencyMS(Long serverHeartbeatFrequencyMS) { + this.serverHeartbeatFrequencyMS = serverHeartbeatFrequencyMS; + } + + /** + * @param serverMinHeartbeatFrequencyMS in msec + * @see com.mongodb.connection.ServerSettings.Builder#minHeartbeatFrequency(long, TimeUnit) + */ + public void setServerMinHeartbeatFrequencyMS(Long serverMinHeartbeatFrequencyMS) { + this.serverMinHeartbeatFrequencyMS = serverMinHeartbeatFrequencyMS; + } + + // --> Cluster Settings + + private @Nullable String clusterSrvHost = DEFAULT_MONGO_SETTINGS.getClusterSettings().getSrvHost(); + private List clusterHosts = Collections.emptyList(); + private @Nullable ClusterConnectionMode clusterConnectionMode = null; + private ClusterType custerRequiredClusterType = DEFAULT_MONGO_SETTINGS.getClusterSettings().getRequiredClusterType(); + private String clusterRequiredReplicaSetName = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getRequiredReplicaSetName(); + private long clusterLocalThresholdMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getLocalThreshold(TimeUnit.MILLISECONDS); + private long clusterServerSelectionTimeoutMS = DEFAULT_MONGO_SETTINGS.getClusterSettings() + .getServerSelectionTimeout(TimeUnit.MILLISECONDS); + + /** + * @param clusterSrvHost + * @see com.mongodb.connection.ClusterSettings.Builder#srvHost(String) + */ + public void setClusterSrvHost(String clusterSrvHost) { + this.clusterSrvHost = clusterSrvHost; + } + + /** + * @param clusterHosts + * @see com.mongodb.connection.ClusterSettings.Builder#hosts(List) + */ + public void setClusterHosts(ServerAddress[] clusterHosts) { + this.clusterHosts = Arrays.asList(clusterHosts); + } + + /** + * ???? + * + * @param clusterConnectionMode + * @see com.mongodb.connection.ClusterSettings.Builder#mode(ClusterConnectionMode) + */ + public void setClusterConnectionMode(ClusterConnectionMode clusterConnectionMode) { + this.clusterConnectionMode = clusterConnectionMode; + } + + /** + * @param custerRequiredClusterType + * @see com.mongodb.connection.ClusterSettings.Builder#requiredClusterType(ClusterType) + */ + public void setCusterRequiredClusterType(ClusterType custerRequiredClusterType) { + this.custerRequiredClusterType = custerRequiredClusterType; + } + + /** + * @param clusterRequiredReplicaSetName + * @see com.mongodb.connection.ClusterSettings.Builder#requiredReplicaSetName(String) + */ + public void setClusterRequiredReplicaSetName(String clusterRequiredReplicaSetName) { + this.clusterRequiredReplicaSetName = clusterRequiredReplicaSetName; + } + + /** + * @param clusterLocalThresholdMS in msec + * @see com.mongodb.connection.ClusterSettings.Builder#localThreshold(long, TimeUnit) + */ + public void setClusterLocalThresholdMS(long clusterLocalThresholdMS) { + this.clusterLocalThresholdMS = clusterLocalThresholdMS; + } + + /** + * @param clusterServerSelectionTimeoutMS in msec + * @see com.mongodb.connection.ClusterSettings.Builder#serverSelectionTimeout(long, TimeUnit) + */ + public void setClusterServerSelectionTimeoutMS(long clusterServerSelectionTimeoutMS) { + this.clusterServerSelectionTimeoutMS = clusterServerSelectionTimeoutMS; + } + + // --> ConnectionPoolSettings + + private Integer poolMaxSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMaxSize(); + private Integer poolMinSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMinSize(); + private Long poolMaxWaitTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxWaitTime(TimeUnit.MILLISECONDS); + private Long poolMaxConnectionLifeTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionLifeTime(TimeUnit.MILLISECONDS); + private Long poolMaxConnectionIdleTimeMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaxConnectionIdleTime(TimeUnit.MILLISECONDS); + private Long poolMaintenanceInitialDelayMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceInitialDelay(TimeUnit.MILLISECONDS); + private Long poolMaintenanceFrequencyMS = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings() + .getMaintenanceFrequency(TimeUnit.MILLISECONDS); + + /** + * @param poolMaxSize + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxSize(int) + */ + public void setPoolMaxSize(Integer poolMaxSize) { + this.poolMaxSize = poolMaxSize; + } + + /** + * @param poolMinSize + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#minSize(int) + */ + public void setPoolMinSize(Integer poolMinSize) { + this.poolMinSize = poolMinSize; + } + + /** + * @param poolMaxWaitTimeMS in mesec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxWaitTime(long, TimeUnit) + */ + public void setPoolMaxWaitTimeMS(Long poolMaxWaitTimeMS) { + this.poolMaxWaitTimeMS = poolMaxWaitTimeMS; + } + + /** + * @param poolMaxConnectionLifeTimeMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionLifeTime(long, TimeUnit) + */ + public void setPoolMaxConnectionLifeTimeMS(Long poolMaxConnectionLifeTimeMS) { + this.poolMaxConnectionLifeTimeMS = poolMaxConnectionLifeTimeMS; + } + + /** + * @param poolMaxConnectionIdleTimeMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maxConnectionIdleTime(long, TimeUnit) + */ + public void setPoolMaxConnectionIdleTimeMS(Long poolMaxConnectionIdleTimeMS) { + this.poolMaxConnectionIdleTimeMS = poolMaxConnectionIdleTimeMS; + } + + /** + * @param poolMaintenanceInitialDelayMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceInitialDelay(long, TimeUnit) + */ + public void setPoolMaintenanceInitialDelayMS(Long poolMaintenanceInitialDelayMS) { + this.poolMaintenanceInitialDelayMS = poolMaintenanceInitialDelayMS; + } + + /** + * @param poolMaintenanceFrequencyMS in msec + * @see com.mongodb.connection.ConnectionPoolSettings.Builder#maintenanceFrequency(long, TimeUnit) + */ + public void setPoolMaintenanceFrequencyMS(Long poolMaintenanceFrequencyMS) { + this.poolMaintenanceFrequencyMS = poolMaintenanceFrequencyMS; + } + + // --> SSL Settings + + private Boolean sslEnabled = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled(); + private Boolean sslInvalidHostNameAllowed = DEFAULT_MONGO_SETTINGS.getSslSettings().isInvalidHostNameAllowed(); + private String sslProvider = DEFAULT_MONGO_SETTINGS.getSslSettings().isEnabled() + ? DEFAULT_MONGO_SETTINGS.getSslSettings().getContext().getProvider().getName() + : ""; + + /** + * @param sslEnabled + * @see com.mongodb.connection.SslSettings.Builder#enabled(boolean) + */ + public void setSslEnabled(Boolean sslEnabled) { + this.sslEnabled = sslEnabled; + } + + /** + * @param sslInvalidHostNameAllowed + * @see com.mongodb.connection.SslSettings.Builder#invalidHostNameAllowed(boolean) + */ + public void setSslInvalidHostNameAllowed(Boolean sslInvalidHostNameAllowed) { + this.sslInvalidHostNameAllowed = sslInvalidHostNameAllowed; + } + + /** + * @param sslProvider + * @see com.mongodb.connection.SslSettings.Builder#context(SSLContext) + * @see SSLContext#getInstance(String) + */ + public void setSslProvider(String sslProvider) { + this.sslProvider = sslProvider; + } + + // encryption and retry + + private @Nullable AutoEncryptionSettings autoEncryptionSettings; + + /** + * @param applicationName + * @see MongoClientSettings.Builder#applicationName(String) + */ + public void setApplicationName(@Nullable String applicationName) { + this.applicationName = applicationName; + } + + /** + * @param retryReads + * @see MongoClientSettings.Builder#retryReads(boolean) + */ + public void setRetryReads(@Nullable Boolean retryReads) { + this.retryReads = retryReads; + } + + /** + * @param readConcern + * @see MongoClientSettings.Builder#readConcern(ReadConcern) + */ + public void setReadConcern(ReadConcern readConcern) { + this.readConcern = readConcern; + } + + /** + * @param writeConcern + * @see MongoClientSettings.Builder#writeConcern(WriteConcern) + */ + public void setWriteConcern(WriteConcern writeConcern) { + this.writeConcern = writeConcern; + } + + /** + * @param retryWrites + * @see MongoClientSettings.Builder#retryWrites(boolean) + */ + public void setRetryWrites(@Nullable Boolean retryWrites) { + this.retryWrites = retryWrites; + } + + /** + * @param readPreference + * @see MongoClientSettings.Builder#readPreference(ReadPreference) + */ + public void setReadPreference(ReadPreference readPreference) { + this.readPreference = readPreference; + } + + /** + * @param streamFactoryFactory + * @see MongoClientSettings.Builder#streamFactoryFactory(StreamFactoryFactory) + */ + public void setStreamFactoryFactory(StreamFactoryFactory streamFactoryFactory) { + this.streamFactoryFactory = streamFactoryFactory; + } + + /** + * @param codecRegistry + * @see MongoClientSettings.Builder#codecRegistry(CodecRegistry) + */ + public void setCodecRegistry(CodecRegistry codecRegistry) { + this.codecRegistry = codecRegistry; + } + + /** + * @param autoEncryptionSettings can be {@literal null}. + * @see MongoClientSettings.Builder#autoEncryptionSettings(AutoEncryptionSettings) + */ + public void setAutoEncryptionSettings(@Nullable AutoEncryptionSettings autoEncryptionSettings) { + this.autoEncryptionSettings = autoEncryptionSettings; + } + + @Override + public Class getObjectType() { + return MongoClientSettings.class; + } + + @Override + protected MongoClientSettings createInstance() { + + Builder builder = MongoClientSettings.builder() // + .readPreference(readPreference) // + .writeConcern(writeConcern) // + .readConcern(readConcern) // + .codecRegistry(codecRegistry) // + .applicationName(applicationName) // + .autoEncryptionSettings(autoEncryptionSettings)// + .applyToClusterSettings((settings) -> { + + settings.serverSelectionTimeout(clusterServerSelectionTimeoutMS, TimeUnit.MILLISECONDS); + if(clusterConnectionMode != null) { + settings.mode(clusterConnectionMode); + } + settings.requiredReplicaSetName(clusterRequiredReplicaSetName); + + if (!CollectionUtils.isEmpty(clusterHosts)) { + settings.hosts(clusterHosts); + } + settings.localThreshold(clusterLocalThresholdMS, TimeUnit.MILLISECONDS); +// settings.maxWaitQueueSize(clusterMaxWaitQueueSize); + settings.requiredClusterType(custerRequiredClusterType); + + if (StringUtils.hasText(clusterSrvHost)) { + settings.srvHost(clusterSrvHost); + } + }) // + .applyToConnectionPoolSettings((settings) -> { + + settings.minSize(poolMinSize); + settings.maxSize(poolMaxSize); + settings.maxConnectionIdleTime(poolMaxConnectionIdleTimeMS, TimeUnit.MILLISECONDS); + settings.maxWaitTime(poolMaxWaitTimeMS, TimeUnit.MILLISECONDS); + settings.maxConnectionLifeTime(poolMaxConnectionLifeTimeMS, TimeUnit.MILLISECONDS); +// settings.maxWaitQueueSize(poolMaxWaitQueueSize); + settings.maintenanceFrequency(poolMaintenanceFrequencyMS, TimeUnit.MILLISECONDS); + settings.maintenanceInitialDelay(poolMaintenanceInitialDelayMS, TimeUnit.MILLISECONDS); + }) // + .applyToServerSettings((settings) -> { + + settings.minHeartbeatFrequency(serverMinHeartbeatFrequencyMS, TimeUnit.MILLISECONDS); + settings.heartbeatFrequency(serverHeartbeatFrequencyMS, TimeUnit.MILLISECONDS); + }) // + .applyToSocketSettings((settings) -> { + + settings.connectTimeout(socketConnectTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.readTimeout(socketReadTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.receiveBufferSize(socketReceiveBufferSize); + settings.sendBufferSize(socketSendBufferSize); + }) // + .applyToSslSettings((settings) -> { + + settings.enabled(sslEnabled); + if (ObjectUtils.nullSafeEquals(Boolean.TRUE, sslEnabled)) { + + settings.invalidHostNameAllowed(sslInvalidHostNameAllowed); + try { + settings.context(StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + }); + + if (streamFactoryFactory != null) { + builder = builder.streamFactoryFactory(streamFactoryFactory); + } + if (retryReads != null) { + builder = builder.retryReads(retryReads); + } + if (retryWrites != null) { + builder = builder.retryWrites(retryWrites); + } + + return builder.build(); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java index 745115220..f9cc9d5e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDataIntegrityViolationException.java @@ -16,10 +16,9 @@ package org.springframework.data.mongodb.core; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.WriteResult; +import com.mongodb.WriteConcernResult; /** * Mongo-specific {@link DataIntegrityViolationException}. @@ -30,18 +29,18 @@ public class MongoDataIntegrityViolationException extends DataIntegrityViolation private static final long serialVersionUID = -186980521176764046L; - private final WriteResult writeResult; + private final WriteConcernResult writeResult; private final MongoActionOperation actionOperation; /** - * Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteResult}. + * Creates a new {@link MongoDataIntegrityViolationException} using the given message and {@link WriteConcernResult}. * * @param message the exception message - * @param writeResult the {@link WriteResult} that causes the exception, must not be {@literal null}. + * @param writeResult the {@link WriteConcernResult} that causes the exception, must not be {@literal null}. * @param actionOperation the {@link MongoActionOperation} that caused the exception, must not be {@literal null}. */ - public MongoDataIntegrityViolationException(String message, WriteResult writeResult, - MongoActionOperation actionOperation) { + public MongoDataIntegrityViolationException(String message, WriteConcernResult writeResult, + MongoActionOperation actionOperation) { super(message); @@ -53,11 +52,11 @@ public class MongoDataIntegrityViolationException extends DataIntegrityViolation } /** - * Returns the {@link WriteResult} that caused the exception. + * Returns the {@link WriteConcernResult} that caused the exception. * * @return the writeResult */ - public WriteResult getWriteResult() { + public WriteConcernResult getWriteResult() { return writeResult; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index 9915656b5..b14518b10 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -26,15 +26,14 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import com.mongodb.ClientSessionOptions; -import com.mongodb.DB; import com.mongodb.WriteConcern; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; /** - * Common base class for usage with both {@link com.mongodb.client.MongoClients} and {@link com.mongodb.MongoClient} - * defining common properties such as database name and exception translator. + * Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as + * database name and exception translator. *

* Not intended to be used directly. * @@ -42,7 +41,6 @@ import com.mongodb.client.MongoDatabase; * @author Mark Paluch * @param Client type. * @since 2.1 - * @see SimpleMongoDbFactory * @see SimpleMongoClientDbFactory */ public abstract class MongoDbFactorySupport implements MongoDbFactory { @@ -89,18 +87,18 @@ public abstract class MongoDbFactorySupport implements MongoDbFactory { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb() + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() */ - public MongoDatabase getDb() throws DataAccessException { - return getDb(databaseName); + public MongoDatabase getMongoDatabase() throws DataAccessException { + return getMongoDatabase(getDefaultDatabaseName()); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) */ @Override - public MongoDatabase getDb(String dbName) throws DataAccessException { + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { Assert.hasText(dbName, "Database name must not be empty!"); @@ -181,20 +179,20 @@ public abstract class MongoDbFactorySupport implements MongoDbFactory { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb() + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase() */ @Override - public MongoDatabase getDb() throws DataAccessException { - return proxyMongoDatabase(delegate.getDb()); + public MongoDatabase getMongoDatabase() throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase()); } /* * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String) + * @see org.springframework.data.mongodb.MongoDbFactory#getMongoDatabase(java.lang.String) */ @Override - public MongoDatabase getDb(String dbName) throws DataAccessException { - return proxyMongoDatabase(delegate.getDb(dbName)); + public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException { + return proxyMongoDatabase(delegate.getMongoDatabase(dbName)); } /* @@ -206,15 +204,6 @@ public abstract class MongoDbFactorySupport implements MongoDbFactory { return delegate.getExceptionTranslator(); } - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() - */ - @Override - public DB getLegacyDb() { - return delegate.getLegacyDb(); - } - /* * (non-Javadoc) * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java index e06e83f61..20199306f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoExceptionTranslator.java @@ -29,7 +29,6 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.data.mongodb.BulkOperationException; import org.springframework.data.mongodb.ClientSessionException; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.data.mongodb.UncategorizedMongoDbException; @@ -37,7 +36,6 @@ import org.springframework.data.mongodb.util.MongoDbErrorCodes; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; -import com.mongodb.BulkWriteException; import com.mongodb.MongoBulkWriteException; import com.mongodb.MongoException; import com.mongodb.MongoServerException; @@ -112,10 +110,6 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator return new DataIntegrityViolationException(ex.getMessage(), ex); } - if (ex instanceof BulkWriteException) { - return new BulkOperationException(ex.getMessage(), (BulkWriteException) ex); - } - // All other MongoExceptions if (ex instanceof MongoException) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 635ec96d9..0ec065c2d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -48,7 +48,6 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import com.mongodb.ClientSessionOptions; -import com.mongodb.Cursor; import com.mongodb.ReadPreference; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoCollection; @@ -224,9 +223,10 @@ public interface MongoOperations extends FluentMongoOperations { /** * Executes the given {@link Query} on the entity collection of the specified {@code entityType} backed by a Mongo DB - * {@link Cursor}. + * {@link com.mongodb.client.FindIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to + * be closed. * * @param query the query class that specifies the criteria used to find a record and also an optional fields * specification. Must not be {@literal null}. @@ -239,9 +239,10 @@ public interface MongoOperations extends FluentMongoOperations { /** * Executes the given {@link Query} on the entity collection of the specified {@code entityType} and collection backed - * by a Mongo DB {@link Cursor}. + * by a Mongo DB {@link com.mongodb.client.FindIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to + * be closed. * * @param query the query class that specifies the criteria used to find a record and also an optional fields * specification. Must not be {@literal null}. @@ -360,7 +361,7 @@ public interface MongoOperations extends FluentMongoOperations { IndexOperations indexOps(Class entityClass); /** - * Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level. + * Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.client.MongoDatabase} level. * * @return * @since 1.7 @@ -518,11 +519,11 @@ public interface MongoOperations extends FluentMongoOperations { AggregationResults aggregate(Aggregation aggregation, String collectionName, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. The name of the inputCollection is derived from the inputType of - * the aggregation. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. The name of the inputCollection is + * derived from the inputType of the aggregation. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -537,11 +538,11 @@ public interface MongoOperations extends FluentMongoOperations { CloseableIterator aggregateStream(TypedAggregation aggregation, String collectionName, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class and are returned as stream. The name of the inputCollection is - * derived from the inputType of the aggregation. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class and are returned as stream. The name + * of the inputCollection is derived from the inputType of the aggregation. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -555,10 +556,10 @@ public interface MongoOperations extends FluentMongoOperations { CloseableIterator aggregateStream(TypedAggregation aggregation, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -574,10 +575,10 @@ public interface MongoOperations extends FluentMongoOperations { CloseableIterator aggregateStream(Aggregation aggregation, Class inputType, Class outputType); /** - * Execute an aggregation operation backed by a Mongo DB {@link Cursor}. + * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}. *

- * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link Cursor} that needs to be closed. The raw - * results will be mapped to the given entity class. + * Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that + * needs to be closed. The raw results will be mapped to the given entity class. *

* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling * explanation mode will throw an {@link IllegalArgumentException}. @@ -1373,10 +1374,9 @@ public interface MongoOperations extends FluentMongoOperations { * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific - * support. - *
+ * support.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 88d6202d7..a795cb5e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -35,7 +35,6 @@ import org.bson.codecs.Codec; import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -128,11 +127,6 @@ import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; import com.mongodb.ClientSessionOptions; -import com.mongodb.Cursor; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.Mongo; -import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -174,7 +168,6 @@ import com.mongodb.client.result.UpdateResult; * @author Cimon Lucas * @author Michael J. Simons */ -@SuppressWarnings("deprecation") public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider { private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class); @@ -213,18 +206,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private SessionSynchronization sessionSynchronization = SessionSynchronization.ON_ACTUAL_TRANSACTION; - /** - * Constructor used for a basic template configuration. - * - * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null} or empty. - * @deprecated since 2.2 in favor of {@link #MongoTemplate(com.mongodb.client.MongoClient, String)}. - */ - @Deprecated - public MongoTemplate(MongoClient mongoClient, String databaseName) { - this(new SimpleMongoDbFactory(mongoClient, databaseName), (MongoConverter) null); - } - /** * Constructor used for a basic template configuration. * @@ -316,8 +297,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, /** * Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern} - * configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no - * {@link WriteConcern} will be used. + * configured on the {@link MongoDbFactory} will apply. * * @param writeConcern */ @@ -524,8 +504,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * specification, must not be {@literal null}. * @param collectionName name of the collection to retrieve the objects from * @param documentCallbackHandler the handler that will extract results, one document at a time - * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply - * limits, skips and so on). + * @param preparer allows for customization of the {@link FindIterable} used when iterating over the result set, + * (apply limits, skips and so on). */ protected void executeQuery(Query query, String collectionName, DocumentCallbackHandler documentCallbackHandler, @Nullable CursorPreparer preparer) { @@ -2527,8 +2507,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @param query the query document that specifies the criteria used to find a record. * @param fields the document that specifies the fields to be returned. * @param entityClass the parameterized type of the returned list. - * @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply - * limits, skips and so on). + * @param preparer allows for customization of the {@link FindIterable} used when iterating over the result set, + * (apply limits, skips and so on). * @return the {@link List} of converted objects. */ protected List doFind(String collectionName, Document query, Document fields, Class entityClass, @@ -2797,16 +2777,16 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * Internal method using callback to do queries against the datastore that requires reading a collection of objects. * It will take the following steps *

    - *
  1. Execute the given {@link ConnectionCallback} for a {@link DBCursor}.
  2. - *
  3. Prepare that {@link DBCursor} with the given {@link CursorPreparer} (will be skipped if {@link CursorPreparer} - * is {@literal null}
  4. - *
  5. Iterate over the {@link DBCursor} and applies the given {@link DocumentCallback} to each of the + *
  6. Execute the given {@link ConnectionCallback} for a {@link FindIterable}.
  7. + *
  8. Prepare that {@link FindIterable} with the given {@link CursorPreparer} (will be skipped if + * {@link CursorPreparer} is {@literal null}
  9. + *
  10. Iterate over the {@link FindIterable} and applies the given {@link DocumentCallback} to each of the * {@link Document}s collecting the actual result {@link List}.
  11. *
      * * @param - * @param collectionCallback the callback to retrieve the {@link DBCursor} with - * @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before iterating over it + * @param collectionCallback the callback to retrieve the {@link FindIterable} with + * @param preparer the {@link CursorPreparer} to potentially modify the {@link FindIterable} before iterating over it * @param objectCallback the {@link DocumentCallback} to transform {@link Document}s into the actual domain type * @param collectionName the collection to be queried * @return @@ -2939,7 +2919,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Oliver Gierke * @author Thomas Risberg @@ -2980,7 +2960,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Oliver Gierke * @author Thomas Risberg @@ -3037,7 +3017,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, /** * Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification - * {@link Document} and executes that against the {@link DBCollection}. + * {@link Document} and executes that against the {@link MongoCollection}. * * @author Thomas Risberg */ @@ -3304,14 +3284,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, cursorToUse = cursorToUse.comment(meta.getComment()); } - if (meta.getSnapshot()) { - cursorToUse = cursorToUse.snapshot(meta.getSnapshot()); - } - - if (meta.getMaxScan() != null) { - cursorToUse = cursorToUse.maxScan(meta.getMaxScan()); - } - if (meta.getMaxTimeMsec() != null) { cursorToUse = cursorToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS); } @@ -3396,7 +3368,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } /** - * A {@link CloseableIterator} that is backed by a MongoDB {@link Cursor}. + * A {@link CloseableIterator} that is backed by a MongoDB {@link MongoCollection}. * * @author Thomas Darimont * @since 1.7 @@ -3409,7 +3381,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private DocumentCallback objectReadCallback; /** - * Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}. + * Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link MongoCollection}. * * @param cursor * @param exceptionTranslator diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java index 06ef8307c..c58292673 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientFactoryBean.java @@ -22,7 +22,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; -import com.mongodb.async.client.MongoClientSettings; +import com.mongodb.MongoClientSettings; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java index 480976170..43c3fd737 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoClientSettingsFactoryBean.java @@ -15,192 +15,16 @@ */ package org.springframework.data.mongodb.core; -import java.util.ArrayList; -import java.util.List; - -import org.bson.codecs.configuration.CodecRegistry; -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.util.Assert; - -import com.mongodb.MongoCredential; -import com.mongodb.ReadConcern; -import com.mongodb.ReadPreference; -import com.mongodb.WriteConcern; -import com.mongodb.async.client.MongoClientSettings; -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.connection.StreamFactoryFactory; +import com.mongodb.MongoClientSettings; /** * A factory bean for construction of a {@link MongoClientSettings} instance to be used with the async MongoDB driver. * * @author Mark Paluch * @since 2.0 + * @deprecated since 3.0 - Use {@link MongoClientSettingsFactoryBean} instead. */ -public class ReactiveMongoClientSettingsFactoryBean extends AbstractFactoryBean { +@Deprecated +public class ReactiveMongoClientSettingsFactoryBean extends MongoClientSettingsFactoryBean { - private static final MongoClientSettings DEFAULT_MONGO_SETTINGS = MongoClientSettings.builder().build(); - - private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference(); - private WriteConcern writeConcern = DEFAULT_MONGO_SETTINGS.getWriteConcern(); - private ReadConcern readConcern = DEFAULT_MONGO_SETTINGS.getReadConcern(); - private List credentialList = new ArrayList<>(); - private StreamFactoryFactory streamFactoryFactory = DEFAULT_MONGO_SETTINGS.getStreamFactoryFactory(); - private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry(); - private ClusterSettings clusterSettings = DEFAULT_MONGO_SETTINGS.getClusterSettings(); - private SocketSettings socketSettings = DEFAULT_MONGO_SETTINGS.getSocketSettings(); - private SocketSettings heartbeatSocketSettings = DEFAULT_MONGO_SETTINGS.getHeartbeatSocketSettings(); - private ConnectionPoolSettings connectionPoolSettings = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings(); - private ServerSettings serverSettings = DEFAULT_MONGO_SETTINGS.getServerSettings(); - private SslSettings sslSettings = DEFAULT_MONGO_SETTINGS.getSslSettings(); - - /** - * Set the {@link ReadPreference}. - * - * @param readPreference - */ - public void setReadPreference(ReadPreference readPreference) { - this.readPreference = readPreference; - } - - /** - * Set the {@link WriteConcern}. - * - * @param writeConcern - */ - public void setWriteConcern(WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * Set the {@link ReadConcern}. - * - * @param readConcern - */ - public void setReadConcern(ReadConcern readConcern) { - this.readConcern = readConcern; - } - - /** - * Set the List of {@link MongoCredential}s. - * - * @param credentialList must not be {@literal null}. - */ - public void setCredentialList(List credentialList) { - - Assert.notNull(credentialList, "CredendialList must not be null!"); - - this.credentialList.addAll(credentialList); - } - - /** - * Adds the {@link MongoCredential} to the list of credentials. - * - * @param mongoCredential must not be {@literal null}. - */ - public void addMongoCredential(MongoCredential mongoCredential) { - - Assert.notNull(mongoCredential, "MongoCredential must not be null!"); - - this.credentialList.add(mongoCredential); - } - - /** - * Set the {@link StreamFactoryFactory}. - * - * @param streamFactoryFactory - */ - public void setStreamFactoryFactory(StreamFactoryFactory streamFactoryFactory) { - this.streamFactoryFactory = streamFactoryFactory; - } - - /** - * Set the {@link CodecRegistry}. - * - * @param codecRegistry - */ - public void setCodecRegistry(CodecRegistry codecRegistry) { - this.codecRegistry = codecRegistry; - } - - /** - * Set the {@link ClusterSettings}. - * - * @param clusterSettings - */ - public void setClusterSettings(ClusterSettings clusterSettings) { - this.clusterSettings = clusterSettings; - } - - /** - * Set the {@link SocketSettings}. - * - * @param socketSettings - */ - public void setSocketSettings(SocketSettings socketSettings) { - this.socketSettings = socketSettings; - } - - /** - * Set the heartbeat {@link SocketSettings}. - * - * @param heartbeatSocketSettings - */ - public void setHeartbeatSocketSettings(SocketSettings heartbeatSocketSettings) { - this.heartbeatSocketSettings = heartbeatSocketSettings; - } - - /** - * Set the {@link ConnectionPoolSettings}. - * - * @param connectionPoolSettings - */ - public void setConnectionPoolSettings(ConnectionPoolSettings connectionPoolSettings) { - this.connectionPoolSettings = connectionPoolSettings; - } - - /** - * Set the {@link ServerSettings}. - * - * @param serverSettings - */ - public void setServerSettings(ServerSettings serverSettings) { - this.serverSettings = serverSettings; - } - - /** - * Set the {@link SslSettings}. - * - * @param sslSettings - */ - public void setSslSettings(SslSettings sslSettings) { - this.sslSettings = sslSettings; - } - - @Override - public Class getObjectType() { - return MongoClientSettings.class; - } - - @Override - protected MongoClientSettings createInstance() throws Exception { - - return MongoClientSettings.builder() // - .readPreference(readPreference) // - .writeConcern(writeConcern) // - .readConcern(readConcern) // - .credentialList(credentialList) // - .streamFactoryFactory(streamFactoryFactory) // - .codecRegistry(codecRegistry) // - .clusterSettings(clusterSettings) // - .socketSettings(socketSettings) // - .heartbeatSocketSettings(heartbeatSocketSettings) // - .connectionPoolSettings(connectionPoolSettings) // - .serverSettings(serverSettings) // - .sslSettings(sslSettings) // - .build(); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index f3c37d126..203e622e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core; import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import com.mongodb.client.result.InsertOneResult; import lombok.AccessLevel; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -123,9 +124,6 @@ import org.springframework.util.StringUtils; import com.mongodb.ClientSessionOptions; import com.mongodb.CursorType; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; @@ -151,7 +149,6 @@ import com.mongodb.reactivestreams.client.MapReducePublisher; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; -import com.mongodb.reactivestreams.client.Success; /** * Primary implementation of {@link ReactiveMongoOperations}. It simplifies the use of Reactive MongoDB usage and helps @@ -1605,7 +1602,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati Document document = new Document(dbDoc); - Flux execute = execute(collectionName, collection -> { + Flux execute = execute(collectionName, collection -> { MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.INSERT, collectionName, entityClass, dbDoc, null); @@ -1781,6 +1778,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati .ifPresent(updateOptions::collation); if (update.hasArrayFilters()) { + updateOptions.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument) .map(it -> queryMapper.getMappedObject(it, entity)).collect(Collectors.toList())); } @@ -2357,14 +2355,16 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati protected Mono> doCreateCollection(String collectionName, CreateCollectionOptions collectionOptions) { - return createMono(db -> db.createCollection(collectionName, collectionOptions)).map(success -> { + return createMono(db -> db.createCollection(collectionName, collectionOptions)).doOnSuccess(it -> { - // TODO: Emit a collection created event - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Created collection [{}]", collectionName); - } - return getCollection(collectionName); - }); + + // TODO: Emit a collection created event + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Created collection [{}]", collectionName); + } + + + }).thenReturn(getCollection(collectionName)); } /** @@ -3282,14 +3282,6 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati findPublisherToUse = findPublisherToUse.comment(meta.getComment()); } - if (meta.getSnapshot()) { - findPublisherToUse = findPublisherToUse.snapshot(meta.getSnapshot()); - } - - if (meta.getMaxScan() != null) { - findPublisherToUse = findPublisherToUse.maxScan(meta.getMaxScan()); - } - if (meta.getMaxTimeMsec() != null) { findPublisherToUse = findPublisherToUse.maxTime(meta.getMaxTimeMsec(), TimeUnit.MILLISECONDS); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java index fd5e0fba8..e076c09bf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ScriptOperations.java @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.script.ExecutableMongoScript; import org.springframework.data.mongodb.core.script.NamedMongoScript; import org.springframework.lang.Nullable; -import com.mongodb.DB; /** * Script operations on {@link com.mongodb.DB} level. Allows interaction with server side JavaScript functions. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java index d5d306e87..2743f8abe 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactory.java @@ -19,7 +19,6 @@ import org.springframework.beans.factory.DisposableBean; import com.mongodb.ClientSessionOptions; import com.mongodb.ConnectionString; -import com.mongodb.DB; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; @@ -75,18 +74,6 @@ public class SimpleMongoClientDbFactory extends MongoDbFactorySupport implements DisposableBean { - - /** - * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClientURI}. - * - * @param uri coordinates for a database connection. Must contain a database name and must not be {@literal null}. - * @since 1.7 - */ - public SimpleMongoDbFactory(MongoClientURI uri) { - this(new MongoClient(uri), uri.getDatabase(), true); - } - - /** - * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClient}. - * - * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null} or empty. - * @since 1.7 - */ - public SimpleMongoDbFactory(MongoClient mongoClient, String databaseName) { - this(mongoClient, databaseName, false); - } - - /** - * @param mongoClient - * @param databaseName - * @param mongoInstanceCreated - * @since 1.7 - */ - private SimpleMongoDbFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { - super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() - */ - @Override - public DB getLegacyDb() { - return getMongoClient().getDB(getDefaultDatabaseName()); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getSession(com.mongodb.ClientSessionOptions) - */ - @Override - public ClientSession getSession(ClientSessionOptions options) { - return getMongoClient().startSession(options); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#closeClient() - */ - @Override - protected void closeClient() { - getMongoClient().close(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.mongodb.core.MongoDbFactoryBase#doGetMongoDatabase(java.lang.String) - */ - @Override - protected MongoDatabase doGetMongoDatabase(String dbName) { - return getMongoClient().getDatabase(dbName); - } -} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java index 0a4d99325..73281a247 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -116,7 +116,7 @@ public class DefaultDbRefResolver implements DbRefResolver { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Fetching DBRef '{}' from {}.{}.", dbRef.getId(), - StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getDb().getName(), + StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getMongoDatabase().getName(), dbRef.getCollectionName()); } @@ -156,7 +156,7 @@ public class DefaultDbRefResolver implements DbRefResolver { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Bulk fetching DBRefs {} from {}.{}.", ids, StringUtils.hasText(databaseSource.getDatabaseName()) ? databaseSource.getDatabaseName() - : mongoDbFactory.getDb().getName(), + : mongoDbFactory.getMongoDatabase().getName(), databaseSource.getCollectionName()); } @@ -498,6 +498,6 @@ public class DefaultDbRefResolver implements DbRefResolver { protected MongoCollection getCollection(DBRef dbref) { return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getDb(dbref.getDatabaseName()) - : mongoDbFactory.getDb()).getCollection(dbref.getCollectionName(), Document.class); + : mongoDbFactory.getMongoDatabase()).getCollection(dbref.getCollectionName(), Document.class); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java index f80f2b858..446feb8e0 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceOptions.java @@ -23,8 +23,6 @@ import org.bson.Document; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.lang.Nullable; -import com.mongodb.MapReduceCommand; -import com.mongodb.MapReduceCommand.OutputType; import com.mongodb.client.model.MapReduceAction; /** @@ -38,7 +36,7 @@ public class MapReduceOptions { private @Nullable String outputCollection; private Optional outputDatabase = Optional.empty(); - private MapReduceCommand.OutputType outputType = MapReduceCommand.OutputType.REPLACE; + private @Nullable MapReduceAction mapReduceAction = MapReduceAction.REPLACE; private Map scopeVariables = new HashMap<>(); private Map extraOptions = new HashMap<>(); private @Nullable Boolean jsMode; @@ -103,10 +101,24 @@ public class MapReduceOptions { * the result set fits within the 16MB limit of a single document. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - Use {@link #actionInline()} instead. */ + @Deprecated public MapReduceOptions outputTypeInline() { + return actionInline(); + } - this.outputType = MapReduceCommand.OutputType.INLINE; + /** + * With this option, no collection will be created, and the whole map-reduce operation will happen in RAM. Also, the + * results of the map-reduce will be returned within the result object. Note that this option is possible only when + * the result set fits within the 16MB limit of a single document. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionInline() { + + this.mapReduceAction = null; return this; } @@ -115,10 +127,23 @@ public class MapReduceOptions { * result set and the old collection, the new key will overwrite the old one. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - use {@link #actionMerge()} instead. */ + @Deprecated public MapReduceOptions outputTypeMerge() { + return actionMerge(); + } - this.outputType = MapReduceCommand.OutputType.MERGE; + /** + * This option will merge new data into the old output collection. In other words, if the same key exists in both the + * result set and the old collection, the new key will overwrite the old one. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionMerge() { + + this.mapReduceAction = MapReduceAction.MERGE; return this; } @@ -127,22 +152,50 @@ public class MapReduceOptions { * specified reduce function) will be performed on the two values and the result will be written to the output * collection. If a finalize function was provided, this will be run after the reduce as well. * - * @return + * @return this. + * @deprecated since 3.0 - use {@link #actionReduce()} instead. */ + @Deprecated public MapReduceOptions outputTypeReduce() { - this.outputType = MapReduceCommand.OutputType.REDUCE; + return actionReduce(); + } + + /** + * If documents exists for a given key in the result set and in the old collection, then a reduce operation (using the + * specified reduce function) will be performed on the two values and the result will be written to the output + * collection. If a finalize function was provided, this will be run after the reduce as well. + * + * @return this. + * @since 3.0 + */ + public MapReduceOptions actionReduce() { + + this.mapReduceAction = MapReduceAction.REDUCE; return this; } /** * The output will be inserted into a collection which will atomically replace any existing collection with the same - * name. Note, the default is MapReduceCommand.OutputType.REPLACE + * name. Note, the default is {@link MapReduceAction#REPLACE}. * * @return MapReduceOptions so that methods can be chained in a fluent API style + * @deprecated since 3.0 - Use {@link #actionReplace()} instead. */ + @Deprecated public MapReduceOptions outputTypeReplace() { + return this.actionReplace(); + } - this.outputType = MapReduceCommand.OutputType.REPLACE; + /** + * The output will be inserted into a collection which will atomically replace any existing collection with the same + * name. Note, the default is {@link MapReduceAction#REPLACE}. + * + * @return MapReduceOptions so that methods can be chained in a fluent API style + * @since 3.0 + */ + public MapReduceOptions actionReplace() { + + this.mapReduceAction = MapReduceAction.REPLACE; return this; } @@ -269,10 +322,6 @@ public class MapReduceOptions { return this.outputSharded; } - public MapReduceCommand.OutputType getOutputType() { - return this.outputType; - } - public Map getScopeVariables() { return this.scopeVariables; } @@ -298,34 +347,22 @@ public class MapReduceOptions { } /** - * Return the {@link MapReduceAction} derived from {@link com.mongodb.MapReduceCommand.OutputType}. + * Return the {@link MapReduceAction}. * * @return the mapped action or {@literal null} if the action maps to inline output. * @since 2.0.10 */ @Nullable public MapReduceAction getMapReduceAction() { - - switch (outputType) { - case MERGE: - return MapReduceAction.MERGE; - case REDUCE: - return MapReduceAction.REDUCE; - case REPLACE: - return MapReduceAction.REPLACE; - case INLINE: - return null; - default: - throw new IllegalStateException(String.format("Unknown output type %s for map reduce command.", outputType)); - } + return mapReduceAction; } /** - * @return {@literal true} if {@link OutputType#INLINE} is used. + * @return {@literal true} if {@literal inline} output shall is used. * @since 2.0.10 */ public boolean usesInlineOutput() { - return OutputType.INLINE.equals(outputType); + return null == mapReduceAction; } public Document getOptionsObject() { @@ -361,19 +398,20 @@ public class MapReduceOptions { Document out = new Document(); - switch (getOutputType()) { - case INLINE: - out.put("inline", 1); - break; - case REPLACE: - out.put("replace", outputCollection); - break; - case MERGE: - out.put("merge", outputCollection); - break; - case REDUCE: - out.put("reduce", outputCollection); - break; + if (getMapReduceAction() == null) { + out.put("inline", 1); + } else { + switch (getMapReduceAction()) { + case REPLACE: + out.put("replace", outputCollection); + break; + case MERGE: + out.put("merge", outputCollection); + break; + case REDUCE: + out.put("reduce", outputCollection); + break; + } } outputDatabase.ifPresent(val -> out.append("db", val)); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java index 918691b3c..d53c9b257 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapreduce/MapReduceResults.java @@ -22,8 +22,6 @@ import org.bson.Document; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.MapReduceOutput; - /** * Collects the results of performing a MapReduce operations. * @@ -46,9 +44,7 @@ public class MapReduceResults implements Iterable { * * @param mappedResults must not be {@literal null}. * @param rawResults must not be {@literal null}. - * @deprecated since 1.7. Please use {@link #MapReduceResults(List, MapReduceOutput)} */ - @Deprecated public MapReduceResults(List mappedResults, Document rawResults) { Assert.notNull(mappedResults, "List of mapped results must not be null!"); @@ -61,25 +57,6 @@ public class MapReduceResults implements Iterable { this.outputCollection = parseOutputCollection(rawResults); } - /** - * Creates a new {@link MapReduceResults} from the given mapped results and the {@link MapReduceOutput}. - * - * @param mappedResults must not be {@literal null}. - * @param mapReduceOutput must not be {@literal null}. - * @since 1.7 - */ - public MapReduceResults(List mappedResults, MapReduceOutput mapReduceOutput) { - - Assert.notNull(mappedResults, "MappedResults must not be null!"); - Assert.notNull(mapReduceOutput, "MapReduceOutput must not be null!"); - - this.mappedResults = mappedResults; - this.rawResults = null; - this.mapReduceTiming = parseTiming(mapReduceOutput); - this.mapReduceCounts = parseCounts(mapReduceOutput); - this.outputCollection = parseOutputCollection(mapReduceOutput); - } - /* * (non-Javadoc) * @see java.lang.Iterable#iterator() @@ -175,17 +152,4 @@ public class MapReduceResults implements Iterable { return resultField instanceof Document ? ((Document) resultField).get("collection").toString() : resultField.toString(); } - - private static MapReduceCounts parseCounts(final MapReduceOutput mapReduceOutput) { - return new MapReduceCounts(mapReduceOutput.getInputCount(), mapReduceOutput.getEmitCount(), - mapReduceOutput.getOutputCount()); - } - - private static String parseOutputCollection(final MapReduceOutput mapReduceOutput) { - return mapReduceOutput.getCollectionName(); - } - - private static MapReduceTiming parseTiming(MapReduceOutput mapReduceOutput) { - return new MapReduceTiming(-1, -1, mapReduceOutput.getDuration()); - } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index a9d9bde16..5153493a7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -57,7 +57,7 @@ public interface SubscriptionRequest { * Get the database name of the db. * * @return the name of the database to subscribe to. Can be {@literal null} in which case the default - * {@link MongoDbFactory#getDb() database} is used. + * {@link MongoDbFactory#getMongoDatabase() database} is used. */ @Nullable default String getDatabaseName() { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java index 3bff1fb6b..1addc323e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Meta.java @@ -108,27 +108,6 @@ public class Meta { setValue(MetaKey.MAX_TIME_MS.key, timeout.toMillis()); } - /** - * @return {@literal null} if not set. - * @deprecated since 2.2. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Nullable - @Deprecated - public Long getMaxScan() { - return getValue(MetaKey.MAX_SCAN.key); - } - - /** - * Only scan the specified number of documents. - * - * @param maxScan - * @deprecated since 2.1. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Deprecated - public void setMaxScan(long maxScan) { - setValue(MetaKey.MAX_SCAN.key, maxScan); - } - /** * Add a comment to the query that is propagated to the profile log. * @@ -146,24 +125,6 @@ public class Meta { return getValue(MetaKey.COMMENT.key); } - /** - * Using snapshot prevents the cursor from returning a document more than once. - * - * @param useSnapshot - * @deprecated since 2.1 due to deprecation as of MongoDB 3.6 - */ - @Deprecated - public void setSnapshot(boolean useSnapshot) { - setValue(MetaKey.SNAPSHOT.key, useSnapshot); - } - - /** - * @return {@literal null} if not set. - */ - public boolean getSnapshot() { - return getValue(MetaKey.SNAPSHOT.key, false); - } - /** * @return {@literal null} if not set. * @since 2.1 @@ -186,7 +147,7 @@ public class Meta { } /** - * Add {@link CursorOption} influencing behavior of the {@link com.mongodb.DBCursor}. + * Add {@link CursorOption} influencing behavior of the {@link com.mongodb.client.FindIterable}. * * @param option must not be {@literal null}. * @return diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java index b29763564..0de6f0076 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java @@ -359,20 +359,6 @@ public class Query { return this; } - /** - * @param maxScan - * @return this. - * @see Meta#setMaxScan(long) - * @since 1.6 - * @deprecated since 2.1 due to deprecation in MongoDB 4.0. - */ - @Deprecated - public Query maxScan(long maxScan) { - - meta.setMaxScan(maxScan); - return this; - } - /** * Add a comment to the query that is propagated to the profile log. * @@ -387,19 +373,6 @@ public class Query { return this; } - /** - * @return this. - * @see Meta#setSnapshot(boolean) - * @since 1.6 - * @deprecated since 2.1 due to deprecation as of MongoDB 3.6 - */ - @Deprecated - public Query useSnapshot() { - - meta.setSnapshot(true); - return this; - } - /** * Set the number of documents to return in each response batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java index 19cd8ea18..62514484f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/AsyncInputStreamAdapter.java @@ -31,11 +31,9 @@ import java.util.concurrent.atomic.AtomicLongFieldUpdater; import org.reactivestreams.Publisher; import org.reactivestreams.Subscription; - import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; -import com.mongodb.reactivestreams.client.Success; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; /** @@ -127,7 +125,7 @@ class AsyncInputStreamAdapter implements AsyncInputStream { * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() */ @Override - public Publisher close() { + public Publisher close() { return Mono.create(sink -> { @@ -140,7 +138,7 @@ class AsyncInputStreamAdapter implements AsyncInputStream { } terminatePendingReads(); - sink.success(Success.SUCCESS); + sink.success(); }); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java index 3e303b68c..359d0fb05 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/DataBufferPublisherAdapter.java @@ -32,7 +32,6 @@ import org.reactivestreams.Subscription; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferFactory; -import com.mongodb.reactivestreams.client.Success; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; /** @@ -131,7 +130,7 @@ class DataBufferPublisherAdapter { * @see com.mongodb.reactivestreams.client.gridfs.AsyncInputStream#close() */ @Override - public Publisher close() { + public Publisher close() { return inputStream.close(); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java index d5db0c130..2413e7685 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsResource.java @@ -23,7 +23,6 @@ import java.util.Optional; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; -import org.springframework.data.util.Optionals; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -184,7 +183,7 @@ public class GridFsResource extends InputStreamResource { * * @return never {@literal null}. * @throws com.mongodb.MongoGridFSException in case no content type declared on {@link GridFSFile#getMetadata()} nor - * provided via {@link GridFSFile#getContentType()}. + * provided via {@link GridFSFile}. * @throws IllegalStateException if the file does not {@link #exists()}. */ @SuppressWarnings("deprecation") @@ -192,11 +191,7 @@ public class GridFsResource extends InputStreamResource { Assert.state(exists(), () -> String.format("%s does not exist.", getDescription())); - return Optionals - .firstNonEmpty( - () -> Optional.ofNullable(getGridFSFile().getMetadata()) - .map(it -> it.get(CONTENT_TYPE_FIELD, String.class)), - () -> Optional.ofNullable(getGridFSFile().getContentType())) + return Optional.ofNullable(getGridFSFile().getMetadata()).map(it -> it.get(CONTENT_TYPE_FIELD, String.class)) .orElseThrow(() -> new MongoGridFSException("No contentType data for this GridFS file")); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java index 5cc452483..3d7b639c2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/gridfs/GridFsTemplate.java @@ -257,7 +257,7 @@ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOpe private GridFSBucket getGridFs() { - MongoDatabase db = dbFactory.getDb(); + MongoDatabase db = dbFactory.getMongoDatabase(); return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java index 0366bb761..94dcac336 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AbstractMonitor.java @@ -20,8 +20,8 @@ import java.util.stream.Collectors; import org.bson.Document; -import com.mongodb.MongoClient; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; import com.mongodb.connection.ServerDescription; @@ -34,22 +34,13 @@ import com.mongodb.connection.ServerDescription; */ public abstract class AbstractMonitor { - private final Object mongoClient; - - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #AbstractMonitor(com.mongodb.client.MongoClient)} - */ - @Deprecated - protected AbstractMonitor(MongoClient mongoClient) { - this.mongoClient = mongoClient; - } + private final MongoClient mongoClient; /** * @param mongoClient * @since 2.2 */ - protected AbstractMonitor(com.mongodb.client.MongoClient mongoClient) { + protected AbstractMonitor(MongoClient mongoClient) { this.mongoClient = mongoClient; } @@ -58,30 +49,16 @@ public abstract class AbstractMonitor { } public MongoDatabase getDb(String databaseName) { - - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getDatabase(databaseName); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getDatabase(databaseName); + return mongoClient.getDatabase(databaseName); } protected MongoClient getMongoClient() { - - if (mongoClient instanceof MongoClient) { - return (MongoClient) mongoClient; - } - - throw new IllegalStateException("A com.mongodb.MongoClient is required but was com.mongodb.client.MongoClient"); + return mongoClient; } protected List hosts() { - if (mongoClient instanceof MongoClient) { - return ((MongoClient) mongoClient).getServerAddressList(); - } - - return ((com.mongodb.client.MongoClient) mongoClient).getClusterDescription().getServerDescriptions().stream() - .map(ServerDescription::getAddress).collect(Collectors.toList()); + return mongoClient.getClusterDescription().getServerDescriptions().stream().map(ServerDescription::getAddress) + .collect(Collectors.toList()); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java index 2819aed42..7bf4b9b55 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/AssertMetrics.java @@ -15,14 +15,12 @@ */ package org.springframework.data.mongodb.monitor; -import com.mongodb.MongoClient; import org.bson.Document; import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.DBObject; -import com.mongodb.Mongo; +import com.mongodb.client.MongoClient; /** * JMX Metrics for assertions @@ -33,21 +31,10 @@ import com.mongodb.Mongo; public class AssertMetrics extends AbstractMonitor { /** - * - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #AssertMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public AssertMetrics(MongoClient mongoClient) { - super(mongoClient); - } - - /** - * * @param mongoClient * @since 2.2 */ - public AssertMetrics(com.mongodb.client.MongoClient mongoClient) { + public AssertMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java index 1cb0a4c99..b56fdf769 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BackgroundFlushingMetrics.java @@ -22,7 +22,7 @@ import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Background Flushing @@ -32,20 +32,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Background Flushing Metrics") public class BackgroundFlushingMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #BackgroundFlushingMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public BackgroundFlushingMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public BackgroundFlushingMetrics(com.mongodb.client.MongoClient mongoClient) { + public BackgroundFlushingMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java index 22e9b985f..2afec53f2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/BtreeIndexCounters.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for B-tree index counters @@ -30,20 +30,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Btree Metrics") public class BtreeIndexCounters extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #BtreeIndexCounters(com.mongodb.client.MongoClient)} - */ - @Deprecated - public BtreeIndexCounters(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public BtreeIndexCounters(com.mongodb.client.MongoClient mongoClient) { + public BtreeIndexCounters(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java index b56ccdb61..a4b428e01 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ConnectionMetrics.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Connections @@ -30,21 +30,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Connection metrics") public class ConnectionMetrics extends AbstractMonitor { - /** - * - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #ConnectionMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public ConnectionMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public ConnectionMetrics(com.mongodb.client.MongoClient mongoClient) { + public ConnectionMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java index ea2c78384..23f881399 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/GlobalLockMetrics.java @@ -21,7 +21,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; import com.mongodb.DBObject; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Global Locks @@ -31,20 +31,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Global Lock Metrics") public class GlobalLockMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #GlobalLockMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public GlobalLockMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public GlobalLockMetrics(com.mongodb.client.MongoClient mongoClient) { + public GlobalLockMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java index 6ec809f92..7916fbdc2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/MemoryMetrics.java @@ -20,7 +20,7 @@ import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Memory @@ -30,20 +30,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Memory Metrics") public class MemoryMetrics extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #MemoryMetrics(com.mongodb.client.MongoClient)} - */ - @Deprecated - public MemoryMetrics(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public MemoryMetrics(com.mongodb.client.MongoClient mongoClient) { + public MemoryMetrics(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java index b959004af..4516d5e00 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/OperationCounters.java @@ -21,7 +21,7 @@ import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; import org.springframework.util.NumberUtils; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * JMX Metrics for Operation counters @@ -31,20 +31,11 @@ import com.mongodb.MongoClient; @ManagedResource(description = "Operation Counters") public class OperationCounters extends AbstractMonitor { - /** - * @param mongoClient - * @deprecated since 2.2 in favor of {@link #OperationCounters(com.mongodb.client.MongoClient)} - */ - @Deprecated - public OperationCounters(MongoClient mongoClient) { - super(mongoClient); - } - /** * @param mongoClient * @since 2.2 */ - public OperationCounters(com.mongodb.client.MongoClient mongoClient) { + public OperationCounters(MongoClient mongoClient) { super(mongoClient); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java index 0ec3e7ee6..4982e569c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/monitor/ServerInfo.java @@ -21,10 +21,10 @@ import org.springframework.jmx.export.annotation.ManagedMetric; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.support.MetricType; - -import com.mongodb.MongoClient; import org.springframework.util.StringUtils; +import com.mongodb.client.MongoClient; + /** * Expose basic server information via JMX * @@ -35,7 +35,11 @@ import org.springframework.util.StringUtils; @ManagedResource(description = "Server Information") public class ServerInfo extends AbstractMonitor { - public ServerInfo(MongoClient mongoClient) { + /** + * @param mongoClient + * @since 2.2 + */ + protected ServerInfo(MongoClient mongoClient) { super(mongoClient); } @@ -52,7 +56,7 @@ public class ServerInfo extends AbstractMonitor { * UnknownHostException is not necessary anymore, but clients could have * called this method in a try..catch(UnknownHostException) already */ - return StringUtils.collectionToDelimitedString(hosts(), ";"); + return StringUtils.collectionToDelimitedString(hosts(), ","); } @ManagedMetric(displayName = "Uptime Estimate") diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java index 01977287c..0d6454b88 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/Meta.java @@ -42,15 +42,6 @@ public @interface Meta { */ long maxExecutionTimeMs() default -1; - /** - * Only scan the specified number of documents. - * - * @return - * @deprecated since 2.2. {@code $maxScan} has been removed without replacement in MongoDB 4.2. - */ - @Deprecated - long maxScanDocuments() default -1; - /** * Sets the number of documents to return per batch.
      * Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single @@ -68,13 +59,6 @@ public @interface Meta { */ String comment() default ""; - /** - * Using snapshot prevents the cursor from returning a document more than once. - * - * @return - */ - boolean snapshot() default false; - /** * Set {@link org.springframework.data.mongodb.core.query.Meta.CursorOption} to be used when executing query. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java index 466171c2f..05d864a17 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryMethod.java @@ -278,11 +278,6 @@ public class MongoQueryMethod extends QueryMethod { metaAttributes.setMaxTimeMsec(meta.maxExecutionTimeMs()); } - if (meta.maxScanDocuments() > 0) { - // TODO: Mongo 4 - removal - metaAttributes.setMaxScan(meta.maxScanDocuments()); - } - if (meta.cursorBatchSize() != 0) { metaAttributes.setCursorBatchSize(meta.cursorBatchSize()); } @@ -291,12 +286,6 @@ public class MongoQueryMethod extends QueryMethod { metaAttributes.setComment(meta.comment()); } - if (meta.snapshot()) { - - // TODO: Mongo 4 - removal - metaAttributes.setSnapshot(meta.snapshot()); - } - if (!ObjectUtils.isEmpty(meta.flags())) { for (org.springframework.data.mongodb.core.query.Meta.CursorOption option : meta.flags()) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java index f524e1459..140208151 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingJsonReader.java @@ -1564,30 +1564,11 @@ public class ParameterBindingJsonReader extends AbstractBsonReader { return oid; } - @Deprecated - @Override - public void mark() { - if (mark != null) { - throw new BSONException("A mark already exists; it needs to be reset before creating a new one"); - } - mark = new Mark(); - } - @Override public BsonReaderMark getMark() { return new Mark(); } - @Deprecated - @Override - public void reset() { - if (mark == null) { - throw new BSONException("trying to reset a mark before creating it"); - } - mark.reset(); - mark = null; - } - @Override protected Context getContext() { return (Context) super.getContext(); diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd index bc1c52091..98deb2ac4 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-3.0.xsd @@ -29,13 +29,13 @@ schemaLocation="https://www.springframework.org/schema/data/repository/spring-repository.xsd" /> - - + - + @@ -54,10 +54,10 @@ Defines a MongoDbFactory for connecting to a specific database The name of the MongoDbFactory definition (by default "mongoDbFactory").]]> - + @@ -72,7 +72,20 @@ The name of the database to connect to. Default is 'db'. +The MongoClientURI string. +@Deprecated since 3.0 - Use connection-string instead. + ]]> + + + + + + + @@ -325,14 +338,24 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 + + + + + + + + + + - - - - - - + + + + + + @@ -347,6 +370,22 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 + + + + + + + + + + + + + + + + @@ -357,18 +396,18 @@ Reference to FactoryBean for com.mongodb.AutoEncryptionSettings - @since 2.2 - + - + @@ -380,6 +419,14 @@ The Mongo driver options The name of the MongoClient definition (by default "mongoClient").]]> + + + + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java index a1dd58955..8e1175874 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java @@ -16,9 +16,10 @@ */ import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** * Sample configuration class in default package. @@ -26,11 +27,11 @@ import com.mongodb.MongoClient; * @author Oliver Gierke */ @Configuration -public class ConfigClassInDefaultPackage extends AbstractMongoConfiguration { +public class ConfigClassInDefaultPackage extends AbstractMongoClientConfiguration { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#getDatabaseName() + * @see org.springframework.data.mongodb.config.AbstractMongoClientConfiguration#getDatabaseName() */ @Override protected String getDatabaseName() { @@ -39,10 +40,10 @@ public class ConfigClassInDefaultPackage extends AbstractMongoConfiguration { /* * (non-Javadoc) - * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#mongo() + * @see org.springframework.data.mongodb.config.AbstractMongoClientConfiguration#mongoClient() */ @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java index 37a7ac3ca..a9a8ff183 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoDatabaseUtilsUnitTests.java @@ -59,7 +59,7 @@ public class MongoDatabaseUtilsUnitTests { when(dbFactory.withSession(session)).thenReturn(dbFactory); - when(dbFactory.getDb()).thenReturn(db); + when(dbFactory.getMongoDatabase()).thenReturn(db); when(session.getServerSession()).thenReturn(serverSession); when(session.hasActiveTransaction()).thenReturn(true); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java index 7ceac601e..fadb17452 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/MongoTransactionManagerUnitTests.java @@ -60,8 +60,8 @@ public class MongoTransactionManagerUnitTests { when(dbFactory.withSession(session)).thenReturn(dbFactory); when(dbFactory.withSession(session2)).thenReturn(dbFactory2); - when(dbFactory.getDb()).thenReturn(db); - when(dbFactory2.getDb()).thenReturn(db2); + when(dbFactory.getMongoDatabase()).thenReturn(db); + when(dbFactory2.getMongoDatabase()).thenReturn(db2); when(session.getServerSession()).thenReturn(serverSession); when(session2.getServerSession()).thenReturn(serverSession); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index 862894f73..b4ae2c2b4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -26,7 +26,6 @@ import java.util.Collections; import java.util.Set; import org.junit.Test; - import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -42,10 +41,11 @@ import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** - * Unit tests for {@link AbstractMongoConfiguration}. + * Unit tests for {@link AbstractMongoClientConfiguration}. * * @author Oliver Gierke * @author Thomas Darimont @@ -56,7 +56,7 @@ public class AbstractMongoConfigurationUnitTests { @Test // DATAMONGO-496 public void usesConfigClassPackageAsBaseMappingPackage() throws ClassNotFoundException { - AbstractMongoConfiguration configuration = new SampleMongoConfiguration(); + AbstractMongoClientConfiguration configuration = new SampleMongoConfiguration(); assertThat(configuration.getMappingBasePackage()).isEqualTo(SampleMongoConfiguration.class.getPackage().getName()); assertThat(configuration.getInitialEntitySet()).hasSize(2); assertThat(configuration.getInitialEntitySet()).contains(Entity.class); @@ -134,7 +134,7 @@ public class AbstractMongoConfigurationUnitTests { private static void assertScanningDisabled(final String value) throws ClassNotFoundException { - AbstractMongoConfiguration configuration = new SampleMongoConfiguration() { + AbstractMongoClientConfiguration configuration = new SampleMongoConfiguration() { @Override protected Collection getMappingBasePackages() { return Collections.singleton(value); @@ -146,7 +146,7 @@ public class AbstractMongoConfigurationUnitTests { } @Configuration - static class SampleMongoConfiguration extends AbstractMongoConfiguration { + static class SampleMongoConfiguration extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -155,7 +155,7 @@ public class AbstractMongoConfigurationUnitTests { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Bean @@ -174,7 +174,7 @@ public class AbstractMongoConfigurationUnitTests { } } - static class ConfigurationWithMultipleBasePackages extends AbstractMongoConfiguration { + static class ConfigurationWithMultipleBasePackages extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -183,7 +183,7 @@ public class AbstractMongoConfigurationUnitTests { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java index 20e37c5c6..49c063ff8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfigurationUnitTests.java @@ -26,7 +26,6 @@ import java.util.Collections; import java.util.Set; import org.junit.Test; - import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -43,9 +42,7 @@ import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.Mongo; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; /** * Unit tests for {@link AbstractReactiveMongoConfiguration}. @@ -81,7 +78,8 @@ public class AbstractReactiveMongoConfigurationUnitTests { AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); assertThat(context.getBean(SimpleReactiveMongoDatabaseFactory.class)).isNotNull(); - assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> context.getBean(Mongo.class)); + assertThatExceptionOfType(NoSuchBeanDefinitionException.class) + .isThrownBy(() -> context.getBean(com.mongodb.client.MongoClient.class)); context.close(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java new file mode 100644 index 000000000..c2d5ce6bb --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientNamespaceTests.java @@ -0,0 +1,144 @@ +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.config; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.test.util.ReflectionTestUtils.*; + +import java.util.Collections; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mongodb.core.MongoClientFactoryBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.connection.ClusterType; + +/** + * Integration tests for the MongoDB namespace. + * + * @author Christoph Strobl + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class MongoClientNamespaceTests { + + @Autowired ApplicationContext ctx; + + @Test // DATAMONGO-2384 + public void clientWithJustHostAndPort() { + + assertThat(ctx.containsBean("client-with-just-host-port")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-just-host-port", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isEqualTo("127.0.0.1"); + assertThat(getField(factoryBean, "port")).isEqualTo(27017); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithConnectionString() { + + assertThat(ctx.containsBean("client-with-connection-string")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-string", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")) + .isEqualTo(new ConnectionString("mongodb://127.0.0.1:27017/?replicaSet=rs0")); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithReplicaSet() { + + assertThat(ctx.containsBean("client-with-replica-set")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-replica-set", + MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isNull(); + assertThat(getField(factoryBean, "replicaSet")).isEqualTo("rs0"); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithCredential() { + + assertThat(ctx.containsBean("client-with-auth")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-auth", MongoClientFactoryBean.class); + + assertThat(getField(factoryBean, "host")).isNull(); + assertThat(getField(factoryBean, "port")).isNull(); + assertThat(getField(factoryBean, "connectionString")).isNull(); + assertThat(getField(factoryBean, "credential")).isEqualTo( + Collections.singletonList(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray()))); + assertThat(getField(factoryBean, "replicaSet")).isNull(); + assertThat(getField(factoryBean, "mongoClientSettings")).isNull(); + } + + @Test // DATAMONGO-2384 + public void clientWithClusterSettings() { + + assertThat(ctx.containsBean("client-with-cluster-settings")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-cluster-settings", + MongoClientFactoryBean.class); + + MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); + + assertThat(settings.getClusterSettings().getRequiredClusterType()).isEqualTo(ClusterType.REPLICA_SET); + assertThat(settings.getClusterSettings().getServerSelectionTimeout(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getClusterSettings().getLocalThreshold(TimeUnit.MILLISECONDS)).isEqualTo(5); + assertThat(settings.getClusterSettings().getHosts()).contains(new ServerAddress("localhost", 27018), + new ServerAddress("localhost", 27019), new ServerAddress("localhost", 27020)); + } + + @Test // DATAMONGO-2384 + public void clientWithConnectionPoolSettings() { + + assertThat(ctx.containsBean("client-with-connection-pool-settings")).isTrue(); + MongoClientFactoryBean factoryBean = ctx.getBean("&client-with-connection-pool-settings", + MongoClientFactoryBean.class); + + MongoClientSettings settings = (MongoClientSettings) getField(factoryBean, "mongoClientSettings"); + + assertThat(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMinSize()).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMaxSize()).isEqualTo(20); + assertThat(settings.getConnectionPoolSettings().getMaintenanceFrequency(TimeUnit.MILLISECONDS)).isEqualTo(10); + assertThat(settings.getConnectionPoolSettings().getMaintenanceInitialDelay(TimeUnit.MILLISECONDS)).isEqualTo(11); + assertThat(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)).isEqualTo(30); + assertThat(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)).isEqualTo(15); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java index f11232506..62a89ef08 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoClientParserIntegrationTests.java @@ -17,6 +17,8 @@ package org.springframework.data.mongodb.config; import static org.assertj.core.api.Assertions.*; +import java.util.concurrent.TimeUnit; + import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.support.BeanDefinitionReader; @@ -25,11 +27,14 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; +import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoCredential; import com.mongodb.ReadPreference; +import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; /** * Integration tests for {@link MongoClientParser}. @@ -62,17 +67,13 @@ public class MongoClientParserIntegrationTests { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + context.refresh(); - try { - MongoClient client = context.getBean("mongo-client-with-options-for-write-concern-and-read-preference", - MongoClient.class); - - assertThat(client.getReadPreference()).isEqualTo(ReadPreference.secondary()); - assertThat(client.getWriteConcern()).isEqualTo(WriteConcern.UNACKNOWLEDGED); - } finally { - context.close(); + MongoClientSettings settings = extractClientSettingsFromBean(context, + "mongo-client-with-options-for-write-concern-and-read-preference"); + assertThat(settings.getReadPreference()).isEqualTo(ReadPreference.secondary()); + assertThat(settings.getWriteConcern()).isEqualTo(WriteConcern.UNACKNOWLEDGED); } } @@ -81,16 +82,12 @@ public class MongoClientParserIntegrationTests { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + + context.refresh(); - try { MongoClient client = context.getBean("mongoClient", MongoClient.class); - - assertThat(client.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(client.getAddress().getPort()).isEqualTo(27017); - } finally { - context.close(); + assertThat(client.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); } } @@ -99,16 +96,14 @@ public class MongoClientParserIntegrationTests { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { - try { - MongoClient client = context.getBean("mongo-client-with-credentials", MongoClient.class); + context.refresh(); - assertThat(client.getCredentialsList()) - .contains(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray())); - } finally { - context.close(); + MongoClientSettings settings = extractClientSettingsFromBean(context, "mongo-client-with-credentials"); + + assertThat(settings.getCredential()) + .isEqualTo(MongoCredential.createPlainCredential("jon", "snow", "warg".toCharArray())); } } @@ -117,15 +112,20 @@ public class MongoClientParserIntegrationTests { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongoClient-bean.xml")); - AbstractApplicationContext context = new GenericApplicationContext(factory); - context.refresh(); + try (AbstractApplicationContext context = new GenericApplicationContext(factory)) { + context.refresh(); - try { - - MongoClient client = context.getBean("mongo-client-with-server-selection-timeout", MongoClient.class); - assertThat(client.getMongoClientOptions().getServerSelectionTimeout()).isEqualTo(100); - } finally { - context.close(); + MongoClientSettings settings = extractClientSettingsFromBean(context, + "mongo-client-with-server-selection-timeout"); + assertThat(settings.getClusterSettings().getServerSelectionTimeout(TimeUnit.MILLISECONDS)).isEqualTo(100); } } + + private MongoClientSettings extractClientSettingsFromBean(AbstractApplicationContext context, String beanName) { + return extractClientSettings(context.getBean(beanName, MongoClient.class)); + } + + private MongoClientSettings extractClientSettings(MongoClient client) { + return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java index 17e2ebc68..aabb3088d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoCredentialPropertyEditorUnitTests.java @@ -83,8 +83,6 @@ public class MongoCredentialPropertyEditorUnitTests { static final MongoCredential USER_2_CREDENTIALS = MongoCredential.createCredential(USER_2_NAME, USER_2_DB, USER_2_PWD.toCharArray()); - static final MongoCredential USER_2_CREDENTIALS_CR_AUTH = MongoCredential.createMongoCRCredential(USER_2_NAME, - USER_2_DB, USER_2_PWD.toCharArray()); static final MongoCredential USER_3_CREDENTIALS_X509_AUTH = MongoCredential.createMongoX509Credential(USER_3_NAME); @@ -176,16 +174,6 @@ public class MongoCredentialPropertyEditorUnitTests { assertThat(getValue()).contains(USER_1_CREDENTIALS, USER_2_CREDENTIALS); } - @Test // DATAMONGO-1158 - @SuppressWarnings("unchecked") - public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleUserNamePasswordStringWithDatabaseAndAuthOptions() { - - editor.setAsText(StringUtils.collectionToCommaDelimitedString(Arrays - .asList(USER_1_AUTH_STRING_WITH_PLAIN_AUTH_MECHANISM, USER_2_AUTH_STRING_WITH_MONGODB_CR_AUTH_MECHANISM))); - - assertThat(getValue()).contains(USER_1_CREDENTIALS_PLAIN_AUTH, USER_2_CREDENTIALS_CR_AUTH); - } - @Test // DATAMONGO-1158 @SuppressWarnings("unchecked") public void shouldReturnCredentialsValueCorrectlyWhenGivenMultipleUserNamePasswordStringWithDatabaseAndMixedOptions() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 1195e7896..9736077ea 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -30,12 +30,10 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClientURI; -import com.mongodb.MongoURI; +import com.mongodb.ConnectionString; import com.mongodb.WriteConcern; import com.mongodb.client.MongoDatabase; @@ -62,7 +60,7 @@ public class MongoDbFactoryParserIntegrationTests { SimpleMongoClientDbFactory dbFactory = new SimpleMongoClientDbFactory(MongoTestUtils.client(), "database"); dbFactory.setWriteConcern(WriteConcern.ACKNOWLEDGED); - dbFactory.getDb(); + dbFactory.getMongoDatabase(); assertThat(ReflectionTestUtils.getField(dbFactory, "writeConcern")).isEqualTo(WriteConcern.ACKNOWLEDGED); } @@ -88,7 +86,7 @@ public class MongoDbFactoryParserIntegrationTests { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( "namespace/db-factory-bean-custom-write-concern.xml"); MongoDbFactory factory = ctx.getBean("second", MongoDbFactory.class); - MongoDatabase db = factory.getDb(); + MongoDatabase db = factory.getMongoDatabase(); assertThat(db.getWriteConcern()).isEqualTo(WriteConcern.W2); ctx.close(); @@ -119,11 +117,11 @@ public class MongoDbFactoryParserIntegrationTests { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class); - MongoDatabase db = dbFactory.getDb(); + MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("database"); } @@ -135,7 +133,7 @@ public class MongoDbFactoryParserIntegrationTests { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } @@ -147,7 +145,7 @@ public class MongoDbFactoryParserIntegrationTests { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } @@ -159,24 +157,42 @@ public class MongoDbFactoryParserIntegrationTests { ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues(); assertThat(constructorArguments.getArgumentCount()).isOne(); - ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class); + ValueHolder argument = constructorArguments.getArgumentValue(0, ConnectionString.class); assertThat(argument).isNotNull(); } + @Test // DATAMONGO-2384 + public void usesConnectionStringToCreateClientClient() { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); + + MongoDbFactory dbFactory = ctx.getBean("with-connection-string", MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) + .isInstanceOf(com.mongodb.client.MongoClient.class); + } + + @Test // DATAMONGO-2384 + public void usesMongoClientClientRef() { + + ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml"); + + MongoDbFactory dbFactory = ctx.getBean("with-mongo-client-client-ref", MongoDbFactory.class); + assertThat(dbFactory).isInstanceOf(SimpleMongoClientDbFactory.class); + assertThat(ReflectionTestUtils.getField(dbFactory, "mongoClient")) + .isInstanceOf(com.mongodb.client.MongoClient.class); + } + private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) { - SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class); - MongoDatabase db = dbFactory.getDb(); + SimpleMongoClientDbFactory dbFactory = ctx.getBean("first", SimpleMongoClientDbFactory.class); + MongoDatabase db = dbFactory.getMongoDatabase(); assertThat(db.getName()).isEqualTo("db"); WriteConcern configuredConcern = (WriteConcern) ReflectionTestUtils.getField(dbFactory, "writeConcern"); - MyWriteConcern myDbFactoryWriteConcern = new MyWriteConcern(configuredConcern); - MyWriteConcern myDbWriteConcern = new MyWriteConcern(db.getWriteConcern()); - MyWriteConcern myExpectedWriteConcern = new MyWriteConcern(expectedWriteConcern); - - assertThat(myDbFactoryWriteConcern).isEqualTo(myExpectedWriteConcern); - assertThat(myDbWriteConcern).isEqualTo(myExpectedWriteConcern); - assertThat(myDbWriteConcern).isEqualTo(myDbFactoryWriteConcern); + assertThat(configuredConcern).isEqualTo(expectedWriteConcern); + assertThat(db.getWriteConcern()).isEqualTo(expectedWriteConcern); + assertThat(db.getWriteConcern()).isEqualTo(expectedWriteConcern); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java index a3f1c8984..f04cf44f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests.java @@ -22,11 +22,11 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.List; +import com.mongodb.MongoClientSettings; import org.bson.Document; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.core.MongoClientFactoryBean; @@ -35,11 +35,10 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClient; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; /** - * * @author Mark Pollack * @author Oliver Gierke * @author Thomas Darimont @@ -58,7 +57,8 @@ public class MongoNamespaceReplicaSetTests { assertThat(ctx.containsBean("replicaSetMongo")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&replicaSetMongo"); - List replicaSetSeeds = (List) ReflectionTestUtils.getField(mfb, "replicaSetSeeds"); + MongoClientSettings settings = (MongoClientSettings) ReflectionTestUtils.getField(mfb, "mongoClientSettings"); + List replicaSetSeeds = settings.getClusterSettings().getHosts(); assertThat(replicaSetSeeds).isNotNull(); assertThat(replicaSetSeeds).contains(new ServerAddress(InetAddress.getByName("127.0.0.1"), 10001), @@ -72,7 +72,8 @@ public class MongoNamespaceReplicaSetTests { assertThat(ctx.containsBean("manyReplicaSetMongo")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&manyReplicaSetMongo"); - List replicaSetSeeds = (List) ReflectionTestUtils.getField(mfb, "replicaSetSeeds"); + MongoClientSettings settings = (MongoClientSettings) ReflectionTestUtils.getField(mfb, "mongoClientSettings"); + List replicaSetSeeds = settings.getClusterSettings().getHosts(); assertThat(replicaSetSeeds).isNotNull(); assertThat(replicaSetSeeds).hasSize(3); @@ -90,8 +91,8 @@ public class MongoNamespaceReplicaSetTests { public void testMongoWithReplicaSets() { MongoClient mongo = ctx.getBean(MongoClient.class); - assertThat(mongo.getAllAddress().size()).isEqualTo(2); - List servers = mongo.getAllAddress(); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).isEqualTo(2); + List servers = mongo.getClusterDescription().getClusterSettings().getHosts(); assertThat(servers.get(0).getHost()).isEqualTo("127.0.0.1"); assertThat(servers.get(1).getHost()).isEqualTo("localhost"); assertThat(servers.get(0).getPort()).isEqualTo(10001); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index f37fba863..e6139a678 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -22,7 +22,6 @@ import javax.net.ssl.SSLSocketFactory; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.MongoDbFactory; @@ -33,9 +32,10 @@ import org.springframework.data.mongodb.gridfs.GridFsOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.MongoClientSettings; +import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; +import com.mongodb.client.MongoClient; /** * Integration tests for the MongoDB namespace. @@ -74,9 +74,8 @@ public class MongoNamespaceTests { assertThat(host).isEqualTo("localhost"); assertThat(port).isEqualTo(new Integer(27017)); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory) - .as("By default socketFactory should not be a SSLSocketFactory").isFalse(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options).isNull(); } @Test // DATAMONGO-764 @@ -85,9 +84,9 @@ public class MongoNamespaceTests { assertThat(ctx.containsBean("mongoSsl")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoSsl"); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); } @Test // DATAMONGO-1490 @@ -96,9 +95,9 @@ public class MongoNamespaceTests { assertThat(ctx.containsBean("mongoClientSsl")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoClientSsl"); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); } @Test // DATAMONGO-764 @@ -107,12 +106,11 @@ public class MongoNamespaceTests { assertThat(ctx.containsBean("mongoSslWithCustomSslFactory")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoSslWithCustomSslFactory"); - SSLSocketFactory customSslSocketFactory = ctx.getBean("customSslSocketFactory", SSLSocketFactory.class); - MongoClientOptions options = (MongoClientOptions) getField(mfb, "mongoClientOptions"); + MongoClientSettings options = (MongoClientSettings) getField(mfb, "mongoClientSettings"); - assertThat(options.getSocketFactory() instanceof SSLSocketFactory).as("socketFactory should be a SSLSocketFactory") - .isTrue(); - assertThat(options.getSocketFactory()).isSameAs(customSslSocketFactory); + assertThat(options.getSslSettings().getContext().getSocketFactory() instanceof SSLSocketFactory) + .as("socketFactory should be a SSLSocketFactory").isTrue(); + assertThat(options.getSslSettings().getContext().getProvider().getName()).isEqualTo("SunJSSE"); } @Test @@ -122,8 +120,7 @@ public class MongoNamespaceTests { MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("secondMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); - assertThat(mongo.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(mongo.getAddress().getPort()).isEqualTo(27017); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); } @@ -135,8 +132,7 @@ public class MongoNamespaceTests { MongoDbFactory dbf = (MongoDbFactory) ctx.getBean("thirdMongoDbFactory"); MongoClient mongo = (MongoClient) getField(dbf, "mongoClient"); - assertThat(mongo.getAddress().getHost()).isEqualTo("127.0.0.1"); - assertThat(mongo.getAddress().getPort()).isEqualTo(27017); + assertThat(mongo.getClusterDescription().getClusterSettings().getHosts()).containsExactly(new ServerAddress()); assertThat(getField(dbf, "databaseName")).isEqualTo("database"); } @@ -163,7 +159,7 @@ public class MongoNamespaceTests { assertThat(getField(dbf, "databaseName")).isEqualTo("database"); WriteConcern writeConcern = (WriteConcern) getField(operations, "writeConcern"); - assertThat(writeConcern).isEqualTo(WriteConcern.SAFE); + assertThat(writeConcern).isEqualTo(WriteConcern.ACKNOWLEDGED); } @Test // DATAMONGO-628 @@ -220,15 +216,15 @@ public class MongoNamespaceTests { assertThat(host).isEqualTo("127.0.0.1"); assertThat(port).isEqualTo(new Integer(27017)); - MongoClient mongo = mfb.getObject(); - MongoClientOptions mongoOpts = mongo.getMongoClientOptions(); - - assertThat(mongoOpts.getConnectionsPerHost()).isEqualTo(8); - assertThat(mongoOpts.getConnectTimeout()).isEqualTo(1000); - assertThat(mongoOpts.getMaxWaitTime()).isEqualTo(1500); - - assertThat(mongoOpts.getSocketTimeout()).isEqualTo(1500); - assertThat(mongoOpts.getThreadsAllowedToBlockForConnectionMultiplier()).isEqualTo(4); + // MongoClient mongo = mfb.getObject(); + // MongoClientSettings mongoOpts = mongo.getClusterDescription()..getMongoClientSettings(); + // + // assertThat(mongoOpts.getConnectionsPerHost()).isEqualTo(8); + // assertThat(mongoOpts.getConnectTimeout()).isEqualTo(1000); + // assertThat(mongoOpts.getMaxWaitTime()).isEqualTo(1500); + // + // assertThat(mongoOpts.getSocketTimeout()).isEqualTo(1500); + // assertThat(mongoOpts.getThreadsAllowedToBlockForConnectionMultiplier()).isEqualTo(4); // TODO: check the damned defaults // assertEquals("w", mongoOpts.getWriteConcern().getW()); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index 13afa1ec9..0547a97a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -19,7 +19,9 @@ import static org.assertj.core.api.Assertions.*; import java.util.List; +import com.mongodb.client.MongoClient; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.PropertyValue; @@ -31,10 +33,9 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; -import com.mongodb.Mongo; /** - * Integration tests for {@link MongoParser}. + * Integration tests for {@link MongoClientParser}. * * @author Oliver Gierke */ @@ -51,6 +52,7 @@ public class MongoParserIntegrationTests { } @Test + @Ignore public void readsMongoAttributesCorrectly() { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-bean.xml")); @@ -58,6 +60,7 @@ public class MongoParserIntegrationTests { List values = definition.getPropertyValues().getPropertyValueList(); + values.forEach(System.out::println); assertThat(values.get(2).getValue()).isInstanceOf(BeanDefinition.class); BeanDefinition x = (BeanDefinition) values.get(2).getValue(); @@ -74,7 +77,7 @@ public class MongoParserIntegrationTests { AbstractApplicationContext context = new GenericApplicationContext(factory); context.refresh(); - assertThat(context.getBean("mongo2", Mongo.class)).isNotNull(); + assertThat(context.getBean("mongo2", MongoClient.class)).isNotNull(); context.close(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java deleted file mode 100644 index 725a9cd26..000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.springframework.data.mongodb.config; - -import com.mongodb.WriteConcern; - -public class MyWriteConcern { - - public MyWriteConcern(WriteConcern wc) { - this._w = wc.getWObject(); - this._fsync = wc.getFsync(); - this._j = wc.getJ(); - this._wtimeout = wc.getWtimeout(); - } - - Object _w = 0; - int _wtimeout = 0; - boolean _fsync = false; - boolean _j = false; - boolean _continueOnErrorForInsert = false; - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (_continueOnErrorForInsert ? 1231-2018 : 1237); - result = prime * result + (_fsync ? 1231-2018 : 1237); - result = prime * result + (_j ? 1231-2018 : 1237); - result = prime * result + ((_w == null) ? 0 : _w.hashCode()); - result = prime * result + _wtimeout; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MyWriteConcern other = (MyWriteConcern) obj; - if (_continueOnErrorForInsert != other._continueOnErrorForInsert) - return false; - if (_fsync != other._fsync) - return false; - if (_j != other._j) - return false; - if (_w == null) { - if (other._w != null) - return false; - } else if (!_w.equals(other._w)) - return false; - if (_wtimeout != other._wtimeout) - return false; - return true; - } - -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java index 4c9933995..d35056d09 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsUnitTests.java @@ -100,7 +100,7 @@ public class DefaultBulkOperationsUnitTests { @Before public void setUp() { - when(factory.getDb()).thenReturn(database); + when(factory.getMongoDatabase()).thenReturn(database); when(factory.getExceptionTranslator()).thenReturn(new NullExceptionTranslator()); when(database.getCollection(anyString(), eq(Document.class))).thenReturn(collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 8f215f66a..1a7b11ef2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -62,7 +62,7 @@ public class DefaultIndexOperationsUnitTests { @Before public void setUp() { - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn("OK"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index dedf2aafc..816c5d03b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -89,7 +89,7 @@ public class DefaultReactiveIndexOperationsTests { this.indexOps = new DefaultReactiveIndexOperations(template, collectionName, new QueryMapper(template.getConverter())); - StepVerifier.create(this.collection.dropIndexes()).expectNextCount(1).verifyComplete(); + StepVerifier.create(this.collection.dropIndexes()).verifyComplete(); } private void queryMongoVersionIfNecessary() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java index d4b376767..83ee459b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoAdminIntegrationTests.java @@ -24,8 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.DB; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * This test class assumes that you are already running the MongoDB server. @@ -38,8 +37,6 @@ public class MongoAdminIntegrationTests { private static final Log logger = LogFactory.getLog(MongoAdminIntegrationTests.class); - @SuppressWarnings("unused") private DB testAdminDb; - @Autowired MongoClient mongoClient; MongoAdmin mongoAdmin; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java new file mode 100644 index 000000000..fc9e3320f --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientFactoryBeanUnitTests.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019. 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. + */ + +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.core; + +import static org.assertj.core.api.Assertions.*; + +import java.util.concurrent.TimeUnit; + +import com.mongodb.ServerAddress; +import org.junit.jupiter.api.Test; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; + +/** + * @author Christoph Strobl + */ +class MongoClientFactoryBeanUnitTests { + + static final String CONNECTION_STRING_STRING = "mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000"; + static final ConnectionString CONNECTION_STRING = new ConnectionString(CONNECTION_STRING_STRING); + + @Test // DATAMONGO-2427 + void connectionStringParametersNotOverriddenByDefaults() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setMongoClientSettings(MongoClientSettings.builder().build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("test"); + assertThat(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300000); + assertThat(settings.getClusterSettings().getHosts()).hasSize(2); + } + + @Test // DATAMONGO-2427 + void hostPortParametersNotOverriddenByDefaults() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setPort(2500); + factoryBean.setHost("db2.example.net"); + factoryBean.setReplicaSet("rs0"); + factoryBean.setMongoClientSettings(MongoClientSettings.builder().build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("rs0"); + assertThat(settings.getClusterSettings().getHosts()).containsExactly(new ServerAddress("db2.example.net", 2500)); + } + + @Test // DATAMONGO-2427 + void explicitSettingsOverrideConnectionStringOnes() { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setMongoClientSettings( + MongoClientSettings.builder().applyToClusterSettings(it -> it.requiredReplicaSetName("rs0")) + .applyToSocketSettings(it -> it.connectTimeout(100, TimeUnit.MILLISECONDS)).build()); + + MongoClientSettings settings = factoryBean.computeClientSetting(); + + assertThat(settings.getClusterSettings().getRequiredReplicaSetName()).isEqualTo("rs0"); + assertThat(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(100); + assertThat(settings.getClusterSettings().getHosts()).hasSize(2); + } + + @Test // DATAMONGO-2427 + void hostAndPortPlusConnectionStringError() throws Exception { + + MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); + factoryBean.setConnectionString(CONNECTION_STRING); + factoryBean.setHost("localhost"); + factoryBean.setPort(27017); + assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> factoryBean.createInstance()); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java similarity index 86% rename from spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java index 4e141f171..9d884a38f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientOptionsFactoryBeanIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanIntegrationTests.java @@ -27,16 +27,16 @@ import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.ReadPreference; /** - * Integration tests for {@link MongoClientOptionsFactoryBean}. + * Integration tests for {@link MongoClientSettingsFactoryBean}. * * @author Christoph Strobl */ -public class MongoClientOptionsFactoryBeanIntegrationTests { +public class MongoClientSettingsFactoryBeanIntegrationTests { @Test // DATAMONGO-1158 public void convertsReadPreferenceConcernCorrectly() { - RootBeanDefinition definition = new RootBeanDefinition(MongoClientOptionsFactoryBean.class); + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); definition.getPropertyValues().addPropertyValue("readPreference", "NEAREST"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); @@ -44,7 +44,7 @@ public class MongoClientOptionsFactoryBeanIntegrationTests { factory.registerBeanDefinition("factory", definition); - MongoClientOptionsFactoryBean bean = factory.getBean("&factory", MongoClientOptionsFactoryBean.class); + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); assertThat(ReflectionTestUtils.getField(bean, "readPreference")).isEqualTo((Object) ReadPreference.nearest()); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java new file mode 100644 index 000000000..4b5cf6ddb --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoClientSettingsFactoryBeanUnitTests.java @@ -0,0 +1,66 @@ +/* + * Copyright 2019 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 + * + * https://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.data.mongodb.core; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.data.mongodb.config.ReadConcernPropertyEditor; +import org.springframework.data.mongodb.config.ReadPreferencePropertyEditor; +import org.springframework.test.util.ReflectionTestUtils; + +import com.mongodb.ReadConcern; +import com.mongodb.ReadPreference; + +/** + * Integration tests for {@link MongoClientSettingsFactoryBean}. + * + * @author Christoph Strobl + */ +public class MongoClientSettingsFactoryBeanUnitTests { + + @Test // DATAMONGO-2384 + public void convertsReadPreferenceConcernCorrectly() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); + definition.getPropertyValues().addPropertyValue("readPreference", "NEAREST"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerCustomEditor(ReadPreference.class, ReadPreferencePropertyEditor.class); + + factory.registerBeanDefinition("factory", definition); + + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "readPreference")).isEqualTo(ReadPreference.nearest()); + } + + @Test // DATAMONGO-2384 + public void convertsReadConcernConcernCorrectly() { + + RootBeanDefinition definition = new RootBeanDefinition(MongoClientSettingsFactoryBean.class); + definition.getPropertyValues().addPropertyValue("readConcern", "MAJORITY"); + + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + factory.registerCustomEditor(ReadPreference.class, ReadConcernPropertyEditor.class); + + factory.registerBeanDefinition("factory", definition); + + MongoClientSettingsFactoryBean bean = factory.getBean("&factory", MongoClientSettingsFactoryBean.class); + assertThat(ReflectionTestUtils.getField(bean, "readConcern")).isEqualTo(ReadConcern.MAJORITY); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 7dca9fd5c..44dee0ad7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -100,12 +100,12 @@ import org.springframework.util.StringUtils; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBRef; -import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mongodb.WriteConcern; import com.mongodb.client.FindIterable; import com.mongodb.client.ListIndexesIterable; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.model.Filters; @@ -410,7 +410,7 @@ public class MongoTemplateTests { assertThat(template.indexOps(Person.class).getIndexInfo().isEmpty()).isTrue(); - factory.getDb().getCollection(template.getCollectionName(Person.class)) + factory.getMongoDatabase().getCollection(template.getCollectionName(Person.class)) .createIndex(new org.bson.Document("age", -1), new IndexOptions().name("age_-1").unique(true).sparse(true)); ListIndexesIterable indexInfo = template.getCollection(template.getCollectionName(Person.class)) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 0a93c42c2..7b6d1dfc9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -96,7 +96,6 @@ import org.springframework.lang.Nullable; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.CollectionUtils; -import com.mongodb.DB; import com.mongodb.MongoException; import com.mongodb.MongoNamespace; import com.mongodb.ReadPreference; @@ -157,7 +156,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { public void beforeEach() { when(findIterable.iterator()).thenReturn(cursor); - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(String.class), eq(Document.class))).thenReturn(collection); when(db.runCommand(any(), any(Class.class))).thenReturn(commandResultDocument); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java index 166463272..68dacbcc6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java @@ -33,7 +33,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.core.CollectionOptions.ValidationOptions; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java index 8867c51fc..59ddf9f26 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryCursorPreparerUnitTests.java @@ -31,7 +31,6 @@ import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate.QueryCursorPreparer; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Collation; -import org.springframework.data.mongodb.core.query.Meta; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.FindIterable; @@ -57,9 +56,7 @@ public class QueryCursorPreparerUnitTests { when(cursor.batchSize(anyInt())).thenReturn(cursor); when(cursor.comment(anyString())).thenReturn(cursor); when(cursor.maxTime(anyLong(), any())).thenReturn(cursor); - when(cursor.maxScan(anyLong())).thenReturn(cursor); when(cursor.hint(any())).thenReturn(cursor); - when(cursor.snapshot(anyBoolean())).thenReturn(cursor); when(cursor.noCursorTimeout(anyBoolean())).thenReturn(cursor); when(cursor.collation(any())).thenReturn(cursor); } @@ -82,25 +79,25 @@ public class QueryCursorPreparerUnitTests { verify(cursor).hint(new Document("age", 1)); } - @Test // DATAMONGO-957 - public void doesNotApplyMetaWhenEmpty() { +// @Test // DATAMONGO-957 +// public void doesNotApplyMetaWhenEmpty() { +// +// Query query = query(where("foo").is("bar")); +// query.setMeta(new Meta()); +// +// prepare(query); +// +// verify(cursor, never()).modifiers(any(Document.class)); +// } - Query query = query(where("foo").is("bar")); - query.setMeta(new Meta()); - - prepare(query); - - verify(cursor, never()).modifiers(any(Document.class)); - } - - @Test // DATAMONGO-957 - public void appliesMaxScanCorrectly() { - - Query query = query(where("foo").is("bar")).maxScan(100); - prepare(query); - - verify(cursor).maxScan(100); - } + // @Test // DATAMONGO-957 + // public void appliesMaxScanCorrectly() { + // + // Query query = query(where("foo").is("bar")).maxScan(100); + // prepare(query); + // + // verify(cursor).maxScan(100); + // } @Test // DATAMONGO-957 public void appliesMaxTimeCorrectly() { @@ -120,14 +117,14 @@ public class QueryCursorPreparerUnitTests { verify(cursor).comment("spring data"); } - @Test // DATAMONGO-957 - public void appliesSnapshotCorrectly() { - - Query query = query(where("foo").is("bar")).useSnapshot(); - prepare(query); - - verify(cursor).snapshot(true); - } +// @Test // DATAMONGO-957 +// public void appliesSnapshotCorrectly() { +// +// Query query = query(where("foo").is("bar")).useSnapshot(); +// prepare(query); +// +// verify(cursor).snapshot(true); +// } @Test // DATAMONGO-1480 public void appliesNoCursorTimeoutCorrectly() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java index d0a2369b7..012edc39c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveClientSessionTests.java @@ -39,7 +39,6 @@ import org.springframework.data.util.Version; import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.Success; /** * @author Christoph Strobl @@ -66,7 +65,6 @@ public class ReactiveClientSessionTests { MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); template.insert(new Document("_id", "id-1").append("value", "spring"), COLLECTION_NAME) // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java index 234fa90e1..6fdf4d870 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTransactionTests.java @@ -41,7 +41,6 @@ import org.springframework.data.util.Version; import com.mongodb.ClientSessionOptions; import com.mongodb.reactivestreams.client.ClientSession; import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.Success; /** * Integration tests for Mongo Transactions using {@link ReactiveMongoTemplate}. @@ -76,15 +75,12 @@ public class ReactiveMongoTemplateTransactionTests { template = new ReactiveMongoTemplate(client, DATABASE_NAME); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, COLLECTION_NAME, client).as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); - MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "person", client).as(StepVerifier::create) - .expectNext(Success.SUCCESS) // - .verifyComplete(); + MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "person", client).as(StepVerifier::create).verifyComplete(); MongoTestUtils.createOrReplaceCollection(DATABASE_NAME, "personWithVersionPropertyOfTypeInteger", client) - .as(StepVerifier::create).expectNext(Success.SUCCESS) // + .as(StepVerifier::create) // .verifyComplete(); template.insert(DOCUMENT, COLLECTION_NAME).as(StepVerifier::create).expectNextCount(1).verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 0bd0d4990..6bd65c2f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -93,7 +93,6 @@ import com.mongodb.reactivestreams.client.MapReducePublisher; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; -import com.mongodb.reactivestreams.client.Success; /** * Unit tests for {@link ReactiveMongoTemplate}. @@ -116,7 +115,7 @@ public class ReactiveMongoTemplateUnitTests { @Mock Publisher runCommandPublisher; @Mock Publisher updateResultPublisher; @Mock Publisher findAndUpdatePublisher; - @Mock Publisher successPublisher; + @Mock Publisher successPublisher; @Mock DistinctPublisher distinctPublisher; @Mock Publisher deletePublisher; @Mock MapReducePublisher mapReducePublisher; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java index 519b3c748..bb6313451 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveSessionBoundMongoTemplateUnitTests.java @@ -127,7 +127,6 @@ public class ReactiveSessionBoundMongoTemplateUnitTests { when(findPublisher.collation(any())).thenReturn(findPublisher); when(findPublisher.first()).thenReturn(resultPublisher); when(aggregatePublisher.allowDiskUse(anyBoolean())).thenReturn(aggregatePublisher); - when(aggregatePublisher.useCursor(anyBoolean())).thenReturn(aggregatePublisher); factory = new SimpleReactiveMongoDatabaseFactory(client, "foo"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java index 33410cee6..1c721753a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveUpdateOperationSupportTests.java @@ -20,7 +20,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; import lombok.Data; -import org.springframework.data.mongodb.test.util.MongoTestUtils; import reactor.test.StepVerifier; import org.bson.BsonString; @@ -30,9 +29,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; - -import com.mongodb.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; +import org.springframework.data.mongodb.test.util.MongoTestUtils; /** * Integration tests for {@link ReactiveUpdateOperationSupport}. @@ -51,7 +48,8 @@ public class ReactiveUpdateOperationSupportTests { @Before public void setUp() { - blocking = new MongoTemplate(new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); + blocking = new MongoTemplate( + new SimpleMongoClientDbFactory(MongoTestUtils.client(), "ExecutableUpdateOperationSupportTests")); blocking.dropCollection(STAR_WARS); han = new Person(); @@ -116,8 +114,7 @@ public class ReactiveUpdateOperationSupportTests { public void updateAllMatching() { template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).all() - .as(StepVerifier::create) - .consumeNextWith(actual -> { + .as(StepVerifier::create).consumeNextWith(actual -> { assertThat(actual.getModifiedCount()).isEqualTo(1L); assertThat(actual.getUpsertedId()).isNull(); @@ -128,8 +125,7 @@ public class ReactiveUpdateOperationSupportTests { public void updateWithDifferentDomainClassAndCollection() { template.update(Jedi.class).inCollection(STAR_WARS).matching(query(where("_id").is(han.getId()))) - .apply(new Update().set("name", "Han")).all().as(StepVerifier::create) - .consumeNextWith(actual -> { + .apply(new Update().set("name", "Han")).all().as(StepVerifier::create).consumeNextWith(actual -> { assertThat(actual.getModifiedCount()).isEqualTo(1L); assertThat(actual.getUpsertedId()).isNull(); @@ -143,8 +139,7 @@ public class ReactiveUpdateOperationSupportTests { public void findAndModify() { template.update(Person.class).matching(queryHan()).apply(new Update().set("firstname", "Han")).findAndModify() - .as(StepVerifier::create) - .expectNext(han).verifyComplete(); + .as(StepVerifier::create).expectNext(han).verifyComplete(); assertThat(blocking.findOne(queryHan(), Person.class)).isNotEqualTo(han).hasFieldOrPropertyWithValue("firstname", "Han"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java index b49ff9794..22acab58a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateTests.java @@ -100,9 +100,9 @@ public class SessionBoundMongoTemplateTests { MongoDbFactory factory = new SimpleMongoClientDbFactory(client, "session-bound-mongo-template-tests") { @Override - public MongoDatabase getDb() throws DataAccessException { + public MongoDatabase getMongoDatabase() throws DataAccessException { - MongoDatabase spiedDatabse = Mockito.spy(super.getDb()); + MongoDatabase spiedDatabse = Mockito.spy(super.getMongoDatabase()); spiedDatabases.add(spiedDatabse); return spiedDatabse; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java index 41b62aa2b..eee395f82 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SessionBoundMongoTemplateUnitTests.java @@ -112,7 +112,6 @@ public class SessionBoundMongoTemplateUnitTests { when(aggregateIterable.allowDiskUse(anyBoolean())).thenReturn(aggregateIterable); when(aggregateIterable.batchSize(anyInt())).thenReturn(aggregateIterable); when(aggregateIterable.map(any())).thenReturn(aggregateIterable); - when(aggregateIterable.useCursor(anyBoolean())).thenReturn(aggregateIterable); when(aggregateIterable.into(any())).thenReturn(Collections.emptyList()); when(mongoIterable.iterator()).thenReturn(cursor); when(distinctIterable.map(any())).thenReturn(distinctIterable); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java similarity index 84% rename from spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java rename to spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java index 8a2961e62..7369c8272 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDbFactoryUnitTests.java @@ -30,20 +30,20 @@ import org.springframework.aop.framework.AopProxyUtils; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.test.util.ReflectionTestUtils; -import com.mongodb.MongoClientURI; +import com.mongodb.ConnectionString; import com.mongodb.client.ClientSession; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; /** - * Unit tests for {@link SimpleMongoDbFactory}. + * Unit tests for {@link SimpleMongoClientDbFactory}. * * @author Oliver Gierke * @author Christoph Strobl * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) -public class SimpleMongoDbFactoryUnitTests { +public class SimpleMongoClientDbFactoryUnitTests { @Mock MongoClient mongo; @Mock ClientSession clientSession; @@ -72,8 +72,9 @@ public class SimpleMongoDbFactoryUnitTests { @SuppressWarnings("deprecation") public void mongoUriConstructor() { - MongoClientURI mongoURI = new MongoClientURI("mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); - MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoURI); + ConnectionString mongoURI = new ConnectionString( + "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); + MongoDbFactory mongoDbFactory = new SimpleMongoClientDbFactory(mongoURI); assertThat(getField(mongoDbFactory, "databaseName").toString()).isEqualTo("myDatabase"); } @@ -81,8 +82,9 @@ public class SimpleMongoDbFactoryUnitTests { @Test // DATAMONGO-1158 public void constructsMongoClientAccordingToMongoUri() { - MongoClientURI uri = new MongoClientURI("mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); - SimpleMongoDbFactory factory = new SimpleMongoDbFactory(uri); + ConnectionString uri = new ConnectionString( + "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); + SimpleMongoClientDbFactory factory = new SimpleMongoClientDbFactory(uri); assertThat(getField(factory, "databaseName").toString()).isEqualTo("myDataBase"); } @@ -95,7 +97,7 @@ public class SimpleMongoDbFactoryUnitTests { MongoDbFactory factory = new SimpleMongoClientDbFactory(mongo, "foo"); MongoDbFactory wrapped = factory.withSession(clientSession).withSession(clientSession); - InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getDb()); + InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase()); Object singletonTarget = AopProxyUtils .getSingletonTarget(ReflectionTestUtils.getField(invocationHandler, "advised")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java index d0a7f44cf..b4f97ce98 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerUnitTests.java @@ -173,13 +173,14 @@ public class SpelExpressionTransformerUnitTests { @Test // DATAMONGO-774 public void shouldRenderNestedParameterExpressionResultsInNestedExpressions() { + Document target = ((Document) transform( + "((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", data)); + assertThat( ((Document) transform("((1 + [0].primitiveLongValue) + [0].primitiveDoubleValue) * [0].doubleValue.longValue()", - data)).toJson()) + data))) .isEqualTo(new Document("$multiply", - Arrays. asList( - new Document("$add", Arrays. asList(1, new Document("$numberLong", "42"), 1.2345D)), - new Document("$numberLong", "23"))).toJson()); + Arrays. asList(new Document("$add", Arrays. asList(1, 42L, 1.2345D)), 23L))); } @Test // DATAMONGO-840 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index e98a4136b..a4a321ea4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -29,7 +29,6 @@ import org.springframework.data.annotation.Id; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.annotation.Version; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.config.EnableMongoAuditing; import org.springframework.data.mongodb.core.KAuditableVersionedEntity; import org.springframework.data.mongodb.core.MongoTemplate; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java index 88eca20b3..4bb8d0a30 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -111,7 +111,7 @@ public class DbRefMappingMongoConverterUnitTests { MongoDatabase dbMock = mock(MongoDatabase.class); MongoCollection collectionMock = mock(MongoCollection.class); - when(dbFactory.getDb()).thenReturn(dbMock); + when(dbFactory.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), eq(Document.class))).thenReturn(collectionMock); FindIterable fi = mock(FindIterable.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java index 0fab4c397..9033f5c5c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolverUnitTests.java @@ -59,7 +59,7 @@ public class DefaultDbRefResolverUnitTests { @Before public void setUp() { - when(factoryMock.getDb()).thenReturn(dbMock); + when(factoryMock.getMongoDatabase()).thenReturn(dbMock); when(dbMock.getCollection(anyString(), any(Class.class))).thenReturn(collectionMock); when(collectionMock.find(any(Document.class))).thenReturn(cursorMock); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 9d116974e..daf6bd064 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -28,6 +28,9 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.model.Filters; +import org.bson.conversions.Bson; import org.bson.types.Code; import org.bson.types.ObjectId; import org.junit.jupiter.api.BeforeEach; @@ -58,7 +61,6 @@ import org.springframework.data.mongodb.core.query.Query; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; -import com.mongodb.QueryBuilder; /** * Unit tests for {@link QueryMapper}. @@ -179,8 +181,8 @@ public class QueryMapperUnitTests { @Test // DATAMONGO-373 void handlesNativelyBuiltQueryCorrectly() { - DBObject query = new QueryBuilder().or(new BasicDBObject("foo", "bar")).get(); - mapper.getMappedObject(new org.bson.Document(query.toMap()), Optional.empty()); + Bson query = new BasicDBObject(Filters.or(new BasicDBObject("foo", "bar")).toBsonDocument(org.bson.Document.class, MongoClientSettings.getDefaultCodecRegistry())); + mapper.getMappedObject(query, Optional.empty()); } @Test // DATAMONGO-369 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 5e585ac2e..7f40c174a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -31,7 +31,6 @@ import java.util.Optional; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -39,7 +38,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoCollectionUtils; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index eddf555ef..def6e4ee1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -74,7 +74,7 @@ public class MongoPersistentEntityIndexCreatorUnitTests { optionsCaptor = ArgumentCaptor.forClass(IndexOptions.class); collectionCaptor = ArgumentCaptor.forClass(String.class); - when(factory.getDb()).thenReturn(db); + when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); when(db.getCollection(collectionCaptor.capture(), eq(org.bson.Document.class))) .thenReturn((MongoCollection) collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java index faef0f359..2b58196b4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java @@ -18,10 +18,9 @@ package org.springframework.data.mongodb.core.mapping.event; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; +import org.springframework.data.mongodb.test.util.MongoTestUtils; import com.mongodb.client.MongoClient; -import org.springframework.data.mongodb.test.util.MongoTestUtils; @Configuration public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java index cebdf0a04..8f02df5d0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/ReactiveMapReduceTests.java @@ -40,7 +40,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.reactivestreams.client.MongoCollection; -import com.mongodb.reactivestreams.client.Success; /** * @author Christoph Strobl @@ -125,8 +124,7 @@ public class ReactiveMapReduceTests { template .mapReduce(new Query(), ValueObject.class, "jmr1", ValueObject.class, mapFunction, reduceFunction, MapReduceOptions.options().outputCollection("jmr1_out")) - .as(StepVerifier::create) - .expectNextCount(4).verifyComplete(); + .as(StepVerifier::create).expectNextCount(4).verifyComplete(); template.find(new Query(), ValueObject.class, "jmr1_out").buffer(4).as(StepVerifier::create) // .consumeNextWith(result -> { @@ -144,8 +142,7 @@ public class ReactiveMapReduceTests { template .mapReduce(new Query(), ValueObject.class, "jmr1", ValueObject.class, mapFunction, reduceFunction, MapReduceOptions.options().outputDatabase("reactive-jrm1-out-db").outputCollection("jmr1_out")) - .as(StepVerifier::create) - .expectNextCount(4).verifyComplete(); + .as(StepVerifier::create).expectNextCount(4).verifyComplete(); Flux.from(factory.getMongoDatabase("reactive-jrm1-out-db").listCollectionNames()).buffer(10) .map(list -> list.contains("jmr1_out")).as(StepVerifier::create).expectNext(true).verifyComplete(); @@ -186,8 +183,8 @@ public class ReactiveMapReduceTests { @Test // DATAMONGO-1890 public void throwsExceptionWhenTryingToLoadFunctionsFromDisk() { - assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> template.mapReduce(new Query(), Person.class, - "foo", ValueObject.class, "classpath:map.js", "classpath:reduce.js", MapReduceOptions.options())) + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> template.mapReduce(new Query(), + Person.class, "foo", ValueObject.class, "classpath:map.js", "classpath:reduce.js", MapReduceOptions.options())) .withMessageContaining("classpath:map.js"); } @@ -198,7 +195,8 @@ public class ReactiveMapReduceTests { StepVerifier .create(collection.insertMany(Arrays.asList(new Document("x", Arrays.asList("a", "b")), new Document("x", Arrays.asList("b", "c")), new Document("x", Arrays.asList("c", "d"))))) - .expectNext(Success.SUCCESS).verifyComplete(); + .expectNextCount(1) // + .verifyComplete(); } @org.springframework.data.mongodb.core.mapping.Document("jmr1") diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index a41b3e25f..770055049 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -213,7 +213,7 @@ public class DefaultMessageListenerContainerTests { @Test // DATAMONGO-1803 public void tailableCursor() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -235,7 +235,7 @@ public class DefaultMessageListenerContainerTests { @Test // DATAMONGO-1803 public void tailableCursorOnEmptyCollection() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); @@ -256,7 +256,7 @@ public class DefaultMessageListenerContainerTests { @Test // DATAMONGO-1803 public void abortsSubscriptionOnError() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); @@ -284,7 +284,7 @@ public class DefaultMessageListenerContainerTests { @Test // DATAMONGO-1803 public void callsDefaultErrorHandlerOnError() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -316,7 +316,7 @@ public class DefaultMessageListenerContainerTests { @EnableIfReplicaSetAvailable public void runsMoreThanOneTaskAtOnce() throws InterruptedException { - dbFactory.getDb().createCollection(COLLECTION_NAME, + dbFactory.getMongoDatabase().createCollection(COLLECTION_NAME, new CreateCollectionOptions().capped(true).maxDocuments(10000).sizeInBytes(10000)); MessageListenerContainer container = new DefaultMessageListenerContainer(template); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index 2ea0e5286..a62ad1752 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -38,8 +38,6 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.messaging.Message.MessageProperties; import org.springframework.data.mongodb.core.messaging.TailableCursorRequest.TailableCursorRequestOptions; - -import com.mongodb.MongoClient; import org.springframework.data.mongodb.test.util.MongoTestUtils; /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java index 2495eb1f7..af3d35348 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsResourceUnitTests.java @@ -39,7 +39,7 @@ public class GridFsResourceUnitTests { public void shouldReadContentTypeCorrectly() { Document metadata = new Document(GridFsResource.CONTENT_TYPE_FIELD, "text/plain"); - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", metadata); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), metadata); GridFsResource resource = new GridFsResource(file); assertThat(resource.getContentType()).isEqualTo("text/plain"); @@ -48,7 +48,7 @@ public class GridFsResourceUnitTests { @Test // DATAMONGO-2240 public void shouldReturnGridFSFile() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", new Document()); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), new Document()); GridFsResource resource = new GridFsResource(file); assertThat(resource.getGridFSFile()).isSameAs(file); @@ -57,7 +57,7 @@ public class GridFsResourceUnitTests { @Test // DATAMONGO-1850 public void shouldThrowExceptionOnEmptyContentType() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", null); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), null); GridFsResource resource = new GridFsResource(file); assertThatThrownBy(resource::getContentType).isInstanceOf(MongoGridFSException.class); @@ -66,7 +66,7 @@ public class GridFsResourceUnitTests { @Test // DATAMONGO-1850 public void shouldThrowExceptionOnEmptyContentTypeInMetadata() { - GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), "foo", new Document()); + GridFSFile file = new GridFSFile(new BsonObjectId(), "foo", 0, 0, new Date(), new Document()); GridFsResource resource = new GridFsResource(file); assertThatThrownBy(resource::getContentType).isInstanceOf(MongoGridFSException.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java index 12e323bfb..2944aff94 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/GridFsTemplateIntegrationTests.java @@ -27,7 +27,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.UUID; import java.util.stream.Stream; import org.bson.BsonObjectId; @@ -36,14 +35,13 @@ import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -52,8 +50,6 @@ import org.springframework.util.StreamUtils; import com.mongodb.MongoGridFSException; import com.mongodb.client.gridfs.GridFSFindIterable; import com.mongodb.client.gridfs.model.GridFSFile; -import com.mongodb.gridfs.GridFS; -import com.mongodb.gridfs.GridFSInputFile; /** * Integration tests for {@link GridFsTemplate}. @@ -73,7 +69,7 @@ public class GridFsTemplateIntegrationTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired GridFsOperations operations; - @Autowired SimpleMongoDbFactory mongoClient; + @Autowired SimpleMongoClientDbFactory mongoClient; @Before public void setUp() { @@ -92,23 +88,23 @@ public class GridFsTemplateIntegrationTests { assertThat(((BsonObjectId) files.get(0).getId()).getValue()).isEqualTo(reference); } - @Test // DATAMONGO-2392 - public void storesAndFindsByUUID() throws IOException { - - UUID uuid = UUID.randomUUID(); - - GridFS fs = new GridFS(mongoClient.getLegacyDb()); - GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); - - in.put("_id", uuid); - in.put("contentType", "application/octet-stream"); - in.save(); - - GridFSFile file = operations.findOne(query(where("_id").is(uuid))); - GridFsResource resource = operations.getResource(file); - - assertThat(resource.exists()).isTrue(); - } + // @Test // DATAMONGO-2392 + // public void storesAndFindsByUUID() throws IOException { + // + // UUID uuid = UUID.randomUUID(); + // + // GridFSFile fs = new GridFSFile(new BsonObjectId(new ObjectId(uuid.to)) + // GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); + // + // in.put("_id", uuid); + // in.put("contentType", "application/octet-stream"); + // in.save(); + // + // GridFSFile file = operations.findOne(query(where("_id").is(uuid))); + // GridFsResource resource = operations.getResource(file); + // + // assertThat(resource.exists()).isTrue(); + // } @Test // DATAMONGO-6 public void writesMetadataCorrectly() throws IOException { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java index 0b18d3662..6656a6cad 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/gridfs/ReactiveGridFsTemplateTests.java @@ -26,7 +26,6 @@ import reactor.test.StepVerifier; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.UUID; import org.bson.BsonObjectId; import org.bson.Document; @@ -46,7 +45,7 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.ContextConfiguration; @@ -54,8 +53,6 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.StreamUtils; import com.mongodb.client.gridfs.model.GridFSFile; -import com.mongodb.gridfs.GridFS; -import com.mongodb.gridfs.GridFSInputFile; import com.mongodb.internal.HexUtils; import com.mongodb.reactivestreams.client.gridfs.AsyncInputStream; import com.mongodb.reactivestreams.client.gridfs.helpers.AsyncStreamHelper; @@ -75,7 +72,7 @@ public class ReactiveGridFsTemplateTests { Resource resource = new ClassPathResource("gridfs/gridfs.xml"); @Autowired ReactiveGridFsOperations operations; - @Autowired SimpleMongoDbFactory mongoClient; + @Autowired SimpleMongoClientDbFactory mongoClient; @Autowired ReactiveMongoDatabaseFactory dbFactory; @Autowired MongoConverter mongoConverter; @@ -143,24 +140,24 @@ public class ReactiveGridFsTemplateTests { }).verifyComplete(); } - @Test // DATAMONGO-2392 - public void storesAndFindsByUUID() throws IOException { - - UUID uuid = UUID.randomUUID(); - - GridFS fs = new GridFS(mongoClient.getLegacyDb()); - GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); - - in.put("_id", uuid); - in.put("contentType", "application/octet-stream"); - in.save(); - - operations.findOne(query(where("_id").is(uuid))).flatMap(operations::getResource) - .flatMapMany(ReactiveGridFsResource::getDownloadStream) // - .transform(DataBufferUtils::join) // - .doOnNext(DataBufferUtils::release).as(StepVerifier::create) // - .expectNextCount(1).verifyComplete(); - } + // @Test // DATAMONGO-2392 + // public void storesAndFindsByUUID() throws IOException { + // + // UUID uuid = UUID.randomUUID(); + // + // GridFS fs = new GridFS(mongoClient.getLegacyDb()); + // GridFSInputFile in = fs.createFile(resource.getInputStream(), "gridfs.xml"); + // + // in.put("_id", uuid); + // in.put("contentType", "application/octet-stream"); + // in.save(); + // + // operations.findOne(query(where("_id").is(uuid))).flatMap(operations::getResource) + // .flatMapMany(ReactiveGridFsResource::getDownloadStream) // + // .transform(DataBufferUtils::join) // + // .doOnNext(DataBufferUtils::release).as(StepVerifier::create) // + // .expectNextCount(1).verifyComplete(); + // } @Test // DATAMONGO-1855 public void writesMetadataCorrectly() throws IOException { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index ae4f74e0a..fcb1cd91d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; /** * This test class assumes that you are already running the MongoDB server. diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java index 723b0acb9..94542b541 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/UserWithComplexIdRepository.java @@ -60,7 +60,7 @@ public interface UserWithComplexIdRepository extends CrudRepository metaWithSpellFixedMaxExecutionTime(); - @Meta(maxScanDocuments = 10) - List metaWithMaxScan(); - @Meta(comment = "foo bar") List metaWithComment(); - @Meta(snapshot = true) - List metaWithSnapshotUsage(); - @Meta(flags = { org.springframework.data.mongodb.core.query.Meta.CursorOption.NO_TIMEOUT }) List metaWithNoCursorTimeout(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index 7a3a7fb45..4261c56a1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -28,15 +28,15 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import org.bson.BSON; +import org.bson.BsonBinarySubType; import org.bson.Document; import org.bson.types.ObjectId; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; - import org.springframework.data.mongodb.core.DocumentTestUtils; import org.springframework.data.mongodb.core.ExecutableFindOperation.ExecutableFind; import org.springframework.data.mongodb.core.MongoOperations; @@ -319,7 +319,7 @@ public class StringBasedMongoQueryUnitTests { org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { '$binary' : '" - + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BSON.B_GENERAL + "'}}"); + + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BsonBinarySubType.BINARY.getValue() + "'}}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } @@ -334,7 +334,7 @@ public class StringBasedMongoQueryUnitTests { org.springframework.data.mongodb.core.query.Query query = mongoQuery.createQuery(accessor); org.springframework.data.mongodb.core.query.Query reference = new BasicQuery("{'lastname' : { $in: [{'$binary' : '" - + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BSON.B_GENERAL + "'}] }}"); + + Base64Utils.encodeToString(binaryData) + "', '$type' : '" + BsonBinarySubType.BINARY.getValue() + "'}] }}"); assertThat(query.getQueryObject().toJson()).isEqualTo(reference.getQueryObject().toJson()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java index cabd2022f..2b3bec647 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java @@ -32,10 +32,7 @@ import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import com.mongodb.DB; -import com.mongodb.DBCollection; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 258f0625f..3924b50ab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -30,7 +30,6 @@ import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.reactivestreams.client.MongoClients; -import com.mongodb.reactivestreams.client.Success; /** * Utility to create (and reuse) imperative and reactive {@code MongoClient} instances. @@ -109,7 +108,7 @@ public class MongoTestUtils { * @param collectionName must not be {@literal null}. * @param client must not be {@literal null}. */ - public static Mono createOrReplaceCollection(String dbName, String collectionName, + public static Mono createOrReplaceCollection(String dbName, String collectionName, com.mongodb.reactivestreams.client.MongoClient client) { com.mongodb.reactivestreams.client.MongoDatabase database = client.getDatabase(dbName) @@ -134,7 +133,6 @@ public class MongoTestUtils { createOrReplaceCollection(dbName, collectionName, client) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); } @@ -155,7 +153,6 @@ public class MongoTestUtils { Mono.from(database.getCollection(collectionName).drop()) // .retryBackoff(3, Duration.ofMillis(250)) // .as(StepVerifier::create) // - .expectNext(Success.SUCCESS) // .verifyComplete(); } @@ -180,9 +177,9 @@ public class MongoTestUtils { } /** - * Create a new {@link com.mongodb.MongoClient} with defaults suitable for replica set usage. + * Create a new {@link com.mongodb.client.MongoClient} with defaults suitable for replica set usage. * - * @return new instance of {@link com.mongodb.MongoClient}. + * @return new instance of {@link com.mongodb.client.MongoClient}. */ public static com.mongodb.client.MongoClient replSetClient() { return com.mongodb.client.MongoClients.create(CONNECTION_STRING); diff --git a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml index 91e90f010..d6aeec9d5 100644 --- a/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml +++ b/spring-data-mongodb/src/test/resources/gridfs/reactive-gridfs.xml @@ -32,7 +32,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/infrastructure.xml b/spring-data-mongodb/src/test/resources/infrastructure.xml index 9a8d1fc9e..5a80d0aca 100644 --- a/spring-data-mongodb/src/test/resources/infrastructure.xml +++ b/spring-data-mongodb/src/test/resources/infrastructure.xml @@ -8,7 +8,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml index 3f75c8b79..66dba8540 100644 --- a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml +++ b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml @@ -5,10 +5,10 @@ xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + diff --git a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml index ae9f93a64..6f8c1ae0c 100644 --- a/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml @@ -5,10 +5,18 @@ xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml b/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml index be74ee612..478f95daf 100644 --- a/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/mongo-bean.xml @@ -6,9 +6,11 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + + + diff --git a/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml b/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml index 20ade07f3..0659bfb97 100644 --- a/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml +++ b/spring-data-mongodb/src/test/resources/namespace/mongoClient-bean.xml @@ -8,16 +8,16 @@ - + - - + + - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml new file mode 100644 index 000000000..912d318ba --- /dev/null +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml index 5602dcf34..dc86edce2 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoDbFactoryNoDatabaseRunningTests-context.xml @@ -8,11 +8,11 @@ http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml index 247f153bd..557524849 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceReplicaSetTests-context.xml @@ -10,9 +10,13 @@ - + + + - + + + - + - - @@ -61,7 +55,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties index 4ac86e45a..ac0a3e904 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/mongo.properties @@ -11,4 +11,6 @@ mongo.fsync=true mongo.slaveOk=true mongoSsl.ssl=true +replicaSetName=rs0 +credential=jon:warg@snow?uri.authMechanism=PLAIN diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index 7d1ccaee1..05eba28ac 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -12,7 +12,7 @@ - + diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml index b5cd79f2b..839d6b2f4 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/repository/config/MongoNamespaceIntegrationTests-context.xml @@ -14,7 +14,7 @@ - + diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 66dfee37c..11533441b 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -14,6 +14,7 @@ toc::[] include::preface.adoc[] include::new-features.adoc[leveloffset=+1] +include::upgrading.adoc[leveloffset=+1] include::{spring-data-commons-docs}/dependencies.adoc[leveloffset=+1] include::{spring-data-commons-docs}/repositories.adoc[leveloffset=+1] diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 7e345c496..6343ae54e 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -302,7 +302,7 @@ The following example shows how to create and use transactions with a `ReactiveM [source,java] ---- @Configuration -static class Config extends AbstractMongoConfiguration { +static class Config extends AbstractMongoClientConfiguration { @Bean ReactiveMongoTransactionManager transactionManager(ReactiveDatabaseFactory factory) { <1> diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index da2b7a58c..8aed43238 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -252,18 +252,18 @@ calling `get()` before the actual conversion Unless explicitly configured, an instance of `MappingMongoConverter` is created by default when you create a `MongoTemplate`. You can create your own instance of the `MappingMongoConverter`. Doing so lets you dictate where in the classpath your domain classes can be found, so that Spring Data MongoDB can extract metadata and construct indexes. Also, by creating your own instance, you can register Spring converters to map specific classes to and from the database. -You can configure the `MappingMongoConverter` as well as `com.mongodb.MongoClient` and MongoTemplate by using either Java-based or XML-based metadata. The following example uses Spring's Java-based configuration: +You can configure the `MappingMongoConverter` as well as `com.mongodb.client.MongoClient` and MongoTemplate by using either Java-based or XML-based metadata. The following example uses Spring's Java-based configuration: .@Configuration class to configure MongoDB mapping support ==== [source,java] ---- @Configuration -public class GeoSpatialAppConfig extends AbstractMongoConfiguration { +public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { @Bean public MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("monogodb://localhost:27017"); } @Override @@ -296,11 +296,11 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration { ---- ==== -`AbstractMongoConfiguration` requires you to implement methods that define a `com.mongodb.MongoClient` as well as provide a database name. `AbstractMongoConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. +`AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation. You can add additional converters to the converter by overriding the `customConversions` method. Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure. -NOTE: `AbstractMongoConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. +NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`. Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows: diff --git a/src/main/asciidoc/reference/migrating.adoc b/src/main/asciidoc/reference/migrating.adoc new file mode 100644 index 000000000..81cfb0780 --- /dev/null +++ b/src/main/asciidoc/reference/migrating.adoc @@ -0,0 +1,61 @@ +[[migrating]] += Migrating + +This chapter coverts major changes and outlines migration steps. + +[[migrating-2.x-to-3.0]] +== 2.x to 3.0 + +=== Dependency Changes + +* `org.mongodb:mongo-java-driver` (uber jar) got replaced with: +** bson-jar +** core-jar +** sync-jar + + +This allows to include eg. just the reactive bits without having to pull in all the sync stuff. +NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please use `org.bson.Document` instead. + +=== Signature Changes + +* `MongoTemplate` no longer supports `com.mongodb.MongoClient` and `com.mongodb.MongoClientOptions`. +Please use `com.mongodb.client.MongoClient` and `com.mongodb.MongoClientSettings` instead. + +In case you're using `AbstractMongoConfiguration` please switch to `AbstractMongoClientInformation`. + +=== Namespace Changes + +The switch to `com.mongodb.client.MongoClient` requires an update of your configuration XML if you have one. +The best way to provide required connection information is by using a connection string. +Please see the https://docs.mongodb.com/manual/reference/connection-string/[MongoDB Documentation] for details. + +[source,xml] +==== +---- + +---- + +---- + + + + + +---- + +---- + + + +---- +==== + + + diff --git a/src/main/asciidoc/reference/mongo-auditing.adoc b/src/main/asciidoc/reference/mongo-auditing.adoc index 90a8e5ce7..eabc532c0 100644 --- a/src/main/asciidoc/reference/mongo-auditing.adoc +++ b/src/main/asciidoc/reference/mongo-auditing.adoc @@ -1,16 +1,6 @@ [[mongo.auditing]] == General Auditing Configuration for MongoDB -To activate auditing functionality, add the Spring Data Mongo `auditing` namespace element to your configuration, as the following example shows: - -.Activating auditing by using XML configuration -==== -[source,xml] ----- - ----- -==== - Since Spring Data MongoDB 1.4, auditing can be enabled by annotating a configuration class with the `@EnableMongoAuditing` annotation, as the followign example shows: .Activating auditing using JavaConfig @@ -28,5 +18,15 @@ class Config { } ---- ==== - If you expose a bean of type `AuditorAware` to the `ApplicationContext`, the auditing infrastructure picks it up automatically and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the `ApplicationContext`, you can select the one to be used by explicitly setting the `auditorAwareRef` attribute of `@EnableMongoAuditing`. + +To activate auditing functionality via XML, add the Spring Data Mongo `auditing` namespace element to your configuration, as the following example shows: + +.Activating auditing by using XML configuration +==== +[source,xml] +---- + +---- +==== + diff --git a/src/main/asciidoc/reference/mongo-custom-conversions.adoc b/src/main/asciidoc/reference/mongo-custom-conversions.adoc index c823e6a81..c4707f389 100644 --- a/src/main/asciidoc/reference/mongo-custom-conversions.adoc +++ b/src/main/asciidoc/reference/mongo-custom-conversions.adoc @@ -85,6 +85,32 @@ public class PersonReadConverter implements Converter { [[mongo.custom-converters.xml]] === Registering Spring Converters with the `MongoConverter` +[source,java] +---- +class MyMongoConfiguration extends AbstractMongoClientConfiguration { + + @Override + public String getDatabaseName() { + return "database"; + } + + @Override + @Bean + public MongoClient mongoClient() { + return MongoClients.create(); + } + + @Override + public CustomConversions customConversions() { + + List> converters = new ArrayList<>(2); + converters.add(new com.example.PersonReadConverter()); + converters.add(new com.example.PersonWriteConverter()); + return new MongoCustomConversions(converters); + } +} +---- + The Mongo Spring namespace provides a convenient way to register Spring `Converter` instances with the `MappingMongoConverter`. The following configuration snippet shows how to manually register converter beans as well as configure the wrapping `MappingMongoConverter` into a `MongoTemplate`: [source,xml] @@ -95,12 +121,12 @@ The Mongo Spring namespace provides a convenient way to register Spring `Convert - + - + diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index c6c2341fb..a97ccf93b 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -41,9 +41,42 @@ public interface PersonRepository extends PagingAndSortingRepository>, by using the standard `com.mongodb.MongoClient` object and the name of the database to use. +* You can instantiate the central helper class of Spring Mongo, <>, by using the standard `com.mongodb.client.MongoClient` object and the name of the database to use. * The mapper works against standard POJO objects without the need for any additional metadata (though you can optionally provide that information. See <>.). * Conventions are used for handling the `id` field, converting it to be an `ObjectId` when stored in the database. * Mapping conventions can use field access. Notice that the `Person` class has only getters. @@ -165,16 +165,16 @@ There is a https://github.com/spring-projects/spring-data-examples[GitHub reposi [[mongodb-connectors]] == Connecting to MongoDB with Spring -One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.MongoClient` or `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. +One of the first tasks when using MongoDB and Spring is to create a `com.mongodb.client.MongoClient` or `com.mongodb.client.MongoClient` object using the IoC container. There are two main ways to do this, either by using Java-based bean metadata or by using XML-based bean metadata. Both are discussed in the following sections. NOTE: For those not familiar with how to configure the Spring container using Java-based bean metadata instead of XML-based metadata, see the high-level introduction in the reference docs https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.0.html#new-java-configuration[here] as well as the detailed documentation https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#beans-java-instantiating-container[here]. [[mongo.mongo-java-config]] === Registering a Mongo Instance by using Java-based Metadata -The following example shows an example of using Java-based bean metadata to register an instance of a `com.mongodb.MongoClient`: +The following example shows an example of using Java-based bean metadata to register an instance of a `com.mongodb.client.MongoClient`: -.Registering a `com.mongodb.MongoClient` object using Java-based bean metadata +.Registering a `com.mongodb.client.MongoClient` object using Java-based bean metadata ==== [source,java] ---- @@ -182,20 +182,20 @@ The following example shows an example of using Java-based bean metadata to regi public class AppConfig { /* - * Use the standard Mongo driver API to create a com.mongodb.MongoClient instance. + * Use the standard Mongo driver API to create a com.mongodb.client.MongoClient instance. */ public @Bean MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("mongodb://localhost:27017"); } } ---- ==== -This approach lets you use the standard `com.mongodb.MongoClient` instance, with the container using Spring's `MongoClientFactoryBean`. As compared to instantiating a `com.mongodb.MongoClient` instance directly, the `FactoryBean` has the added advantage of also providing the container with an `ExceptionTranslator` implementation that translates MongoDB exceptions to exceptions in Spring's portable `DataAccessException` hierarchy for data access classes annotated with the `@Repository` annotation. This hierarchy and the use of `@Repository` is described in https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html[Spring's DAO support features]. +This approach lets you use the standard `com.mongodb.client.MongoClient` instance, with the container using Spring's `MongoClientFactoryBean`. As compared to instantiating a `com.mongodb.client.MongoClient` instance directly, the `FactoryBean` has the added advantage of also providing the container with an `ExceptionTranslator` implementation that translates MongoDB exceptions to exceptions in Spring's portable `DataAccessException` hierarchy for data access classes annotated with the `@Repository` annotation. This hierarchy and the use of `@Repository` is described in https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html[Spring's DAO support features]. The following example shows an example of a Java-based bean metadata that supports exception translation on `@Repository` annotated classes: -.Registering a `com.mongodb.MongoClient` object by using Spring's MongoClientFactoryBean and enabling Spring's exception translation support +.Registering a `com.mongodb.client.MongoClient` object by using Spring's `MongoClientFactoryBean` and enabling Spring's exception translation support ==== [source,java] ---- @@ -203,7 +203,7 @@ The following example shows an example of a Java-based bean metadata that suppor public class AppConfig { /* - * Factory bean that creates the com.mongodb.MongoClient instance + * Factory bean that creates the com.mongodb.client.MongoClient instance */ public @Bean MongoClientFactoryBean mongo() { MongoClientFactoryBean mongo = new MongoClientFactoryBean(); @@ -214,12 +214,12 @@ public class AppConfig { ---- ==== -To access the `com.mongodb.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired Mongo mongo;` field. +To access the `com.mongodb.client.MongoClient` object created by the `MongoClientFactoryBean` in other `@Configuration` classes or your own classes, use a `private @Autowired Mongo mongo;` field. [[mongo.mongo-xml-config]] === Registering a Mongo Instance by Using XML-based Metadata -While you can use Spring's traditional `` XML namespace to register an instance of `com.mongodb.MongoClient` with the container, the XML can be quite verbose, as it is general-purpose. XML namespaces are a better alternative to configuring commonly used objects, such as the Mongo instance. The mongo namespace lets you create a Mongo instance server location, replica-sets, and options. +While you can use Spring's traditional `` XML namespace to register an instance of `com.mongodb.client.MongoClient` with the container, the XML can be quite verbose, as it is general-purpose. XML namespaces are a better alternative to configuring commonly used objects, such as the Mongo instance. The mongo namespace lets you create a Mongo instance server location, replica-sets, and options. To use the Mongo namespace elements, you need to reference the Mongo schema, as follows: @@ -246,26 +246,22 @@ To use the Mongo namespace elements, you need to reference the Mongo schema, as ---- ==== -The following example shows a more advanced configuration with `MongoClientOptions` (note that these are not recommended values): +The following example shows a more advanced configuration with `MongoClientSettings` (note that these are not recommended values): -.XML schema to configure a com.mongodb.MongoClient object with MongoClientOptions +.XML schema to configure a `com.mongodb.client.MongoClient` object with `MongoClientSettings` ==== [source,xml] ---- - + @@ -274,18 +270,20 @@ The following example shows a more advanced configuration with `MongoClientOptio The following example shows a configuration using replica sets: -.XML schema to configure a `com.mongodb.MongoClient` object with Replica Sets +.XML schema to configure a `com.mongodb.client.MongoClient` object with Replica Sets ==== [source,xml] ---- - + + + ---- ==== [[mongo.mongo-db-factory]] === The MongoDbFactory Interface -While `com.mongodb.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDbFactory` interface, shown in the following listing, to bootstrap connectivity to the database: +While `com.mongodb.client.MongoClient` is the entry point to the MongoDB driver API, connecting to a specific MongoDB database instance requires additional information, such as the database name and an optional username and password. With that information, you can obtain a `com.mongodb.client.MongoDatabase` object and access all the functionality of a specific MongoDB database instance. Spring provides the `org.springframework.data.mongodb.core.MongoDbFactory` interface, shown in the following listing, to bootstrap connectivity to the database: [source,java] ---- @@ -309,7 +307,7 @@ public class MongoApp { public static void main(String[] args) throws Exception { - MongoOperations mongoOps = new MongoTemplate(new SimpleMongoDbFactory(new MongoClient(), "database")); + MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDbFactory(MongoClients.create(), "database")); mongoOps.insert(new Person("Joe", 34)); @@ -320,7 +318,7 @@ public class MongoApp { } ---- -The code in bold highlights the use of `SimpleMongoDbFactory` and is the only difference between the listing shown in the <>. +The code in bold highlights the use of `SimpleMongoClientDbFactory` and is the only difference between the listing shown in the <>. NOTE: Use `SimpleMongoClientDbFactory` when choosing `com.mongodb.client.MongoClient` as the entrypoint of choice. @@ -335,7 +333,7 @@ To register a `MongoDbFactory` instance with the container, you write code much public class MongoConfiguration { public @Bean MongoDbFactory mongoDbFactory() { - return new SimpleMongoDbFactory(new MongoClient(), "database"); + return new SimpleMongoClientDbFactory(MongoClients.create(), "database"); } } ---- @@ -345,7 +343,7 @@ MongoDB Server generation 3 changed the authentication model when connecting to [source,java] ---- @Configuration -public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfiguration { +public class ApplicationContextEventTestsAppConfig extends AbstractMongoClientConfiguration { @Override public String getDatabaseName() { @@ -355,24 +353,26 @@ public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfigur @Override @Bean public MongoClient mongoClient() { - return new MongoClient(singletonList(new ServerAddress("127.0.0.1", 27017)), - singletonList(MongoCredential.createCredential("name", "db", "pwd".toCharArray()))); + + MongoClientSettings settings = MongoClientSettings.builder() + .credential(MongoCredential.createCredential("name", "db", "pwd".toCharArray())) + .applyToClusterSettings(settings -> { + settings.hosts(singletonList(new ServerAddress("127.0.0.1", 27017))); + }) + .build(); + + return MongoClients.create(settings); } } ---- -In order to use authentication with XML-based configuration, use the `credentials` attribute on the `` element. +In order to use authentication with XML-based configuration, use the `credential` attribute on the `` element. NOTE: Username and password credentials used in XML-based configuration must be URL-encoded when these contain reserved characters, such as `:`, `%`, `@`, or `,`. The following example shows encoded credentials: `m0ng0@dmin:mo_res:bw6},Qsdxx@admin@database` -> `m0ng0%40dmin:mo_res%3Abw6%7D%2CQsdxx%40admin@database` See https://tools.ietf.org/html/rfc3986#section-2.2[section 2.2 of RFC 3986] for further details. -As of MongoDB java driver 3.7.0 there is an alternative entry point to `MongoClient` via the https://search.maven.org/beta/search?q=a:mongodb-driver-sync[mongodb-driver-sync] artifact. -`com.mongodb.client.MongoClient` is *not* compatible with `com.mongodb.MongoClient` and does not longer support -the legacy `DBObject` codec. Therefore, it cannot be used with `Querydsl` and requires a different configuration. -You can use `AbstractMongoClientConfiguration` to leverage the new `MongoClients` builder API. - [source,java] ---- @Configuration @@ -393,32 +393,27 @@ public class MongoClientConfiguration extends AbstractMongoClientConfiguration { [[mongo.mongo-db-factory-xml]] === Registering a `MongoDbFactory` Instance by Using XML-based Metadata -The `mongo` namespace provides a convenient way to create a `SimpleMongoDbFactory`, as compared to using the `` namespace, as shown in the following example: +The `mongo` namespace provides a convenient way to create a `SimpleMongoClientDbFactory`, as compared to using the `` namespace, as shown in the following example: [source,xml] ---- ---- -If you need to configure additional options on the `com.mongodb.MongoClient` instance that is used to create a `SimpleMongoDbFactory`, you can refer to an existing bean by using the `mongo-ref` attribute as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a `MongoTemplate`: +If you need to configure additional options on the `com.mongodb.client.MongoClient` instance that is used to create a `SimpleMongoClientDbFactory`, you can refer to an existing bean by using the `mongo-ref` attribute as shown in the following example. To show another common usage pattern, the following listing shows the use of a property placeholder, which lets you parametrize the configuration and the creation of a `MongoTemplate`: [source,xml] ---- - + @@ -454,7 +449,7 @@ The next section contains an example of how to work with the `MongoTemplate` in You can use Java to create and register an instance of `MongoTemplate`, as the following example shows: -.Registering a `com.mongodb.MongoClient` object and enabling Spring's exception translation support +.Registering a `com.mongodb.client.MongoClient` object and enabling Spring's exception translation support ==== [source,java] ---- @@ -462,7 +457,7 @@ You can use Java to create and register an instance of `MongoTemplate`, as the f public class AppConfig { public @Bean MongoClient mongoClient() { - return new MongoClient("localhost"); + return MongoClients.create("mongodb://localhost:27017"); } public @Bean MongoTemplate mongoTemplate() { @@ -502,7 +497,7 @@ When in development, it is handy to either log or throw an exception if the `com [[mongo-template.writeconcern]] === `WriteConcern` -If it has not yet been specified through the driver at a higher level (such as `com.mongodb.MongoClient`), you can set the `com.mongodb.WriteConcern` property that the `MongoTemplate` uses for write operations. If the `WriteConcern` property is not set, it defaults to the one set in the MongoDB driver's DB or Collection setting. +If it has not yet been specified through the driver at a higher level (such as `com.mongodb.client.MongoClient`), you can set the `com.mongodb.WriteConcern` property that the `MongoTemplate` uses for write operations. If the `WriteConcern` property is not set, it defaults to the one set in the MongoDB driver's DB or Collection setting. [[mongo-template.writeconcernresolver]] === `WriteConcernResolver` @@ -589,7 +584,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; import com.mongodb.client.MongoClients; @@ -701,7 +696,6 @@ MongoDB collections can contain documents that represent instances of a variety To achieve that, the `MappingMongoConverter` uses a `MongoTypeMapper` abstraction with `DefaultMongoTypeMapper` as its main implementation. Its default behavior to store the fully qualified classname under `_class` inside the document. Type hints are written for top-level documents as well as for every value (if it is a complex type and a subtype of the declared property type). The following example (with a JSON representation at the end) shows how the mapping works: - .Type mapping ==== [source,java] @@ -762,7 +756,7 @@ class CustomMongoTypeMapper extends DefaultMongoTypeMapper { [source,java] ---- @Configuration -class SampleMongoConfiguration extends AbstractMongoConfiguration { +class SampleMongoConfiguration extends AbstractMongoClientConfiguration { @Override protected String getDatabaseName() { @@ -771,7 +765,7 @@ class SampleMongoConfiguration extends AbstractMongoConfiguration { @Override public MongoClient mongoClient() { - return new MongoClient(); + return MongoClients.create(); } @Bean @@ -790,7 +784,7 @@ class SampleMongoConfiguration extends AbstractMongoConfiguration { ---- ==== -Note that the preceding example extends the `AbstractMongoConfiguration` class and overrides the bean definition of the `MappingMongoConverter` where we configured our custom `MongoTypeMapper`. +Note that the preceding example extends the `AbstractMongoClientConfiguration` class and overrides the bean definition of the `MappingMongoConverter` where we configured our custom `MongoTypeMapper`. The following example shows how to use XML to configure a custom `MongoTypeMapper`: @@ -3282,7 +3276,7 @@ MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data ==== [source,java] ---- -class GridFsConfiguration extends AbstractMongoConfiguration { +class GridFsConfiguration extends AbstractMongoClientConfiguration { // … further configuration omitted diff --git a/src/main/asciidoc/reference/reactive-mongodb.adoc b/src/main/asciidoc/reference/reactive-mongodb.adoc index 3e999e6e3..ec4eb581e 100644 --- a/src/main/asciidoc/reference/reactive-mongodb.adoc +++ b/src/main/asciidoc/reference/reactive-mongodb.adoc @@ -145,7 +145,7 @@ One of the first tasks when using MongoDB and Spring is to create a `com.mongodb The following example shows how to use Java-based bean metadata to register an instance of a `com.mongodb.reactivestreams.client.MongoClient`: -.Registering a com.mongodb.MongoClient object using Java based bean metadata +.Registering a `com.mongodb.reactivestreams.client.MongoClient` object using Java based bean metadata ==== [source,java] ---- @@ -168,7 +168,7 @@ An alternative is to register an instance of `com.mongodb.reactivestreams.client The following example shows Java-based bean metadata that supports exception translation on `@Repository` annotated classes: -.Registering a com.mongodb.MongoClient object using Spring's MongoClientFactoryBean and enabling Spring's exception translation support +.Registering a `com.mongodb.reactivestreams.client.MongoClient` object using Spring's MongoClientFactoryBean and enabling Spring's exception translation support ==== [source,java] ---- @@ -250,7 +250,7 @@ public class MongoApp { } ---- -The use of `SimpleMongoDbFactory` is the only difference between the listing shown in the <>. +The use of `SimpleReactiveMongoDatabaseFactory` is the only difference between the listing shown in the <>. [[mongo.reactive.mongo-db-factory-java]] === Registering a ReactiveMongoDatabaseFactory Instance by Using Java-based Metadata @@ -329,7 +329,7 @@ public class AppConfig { There are several overloaded constructors of `ReactiveMongoTemplate`, including: -* `ReactiveMongoTemplate(MongoClient mongo, String databaseName)`: Takes the `com.mongodb.MongoClient` object and the default database name to operate against. +* `ReactiveMongoTemplate(MongoClient mongo, String databaseName)`: Takes the `com.mongodb.reactivestreams.client.MongoClient` object and the default database name to operate against. * `ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory)`: Takes a `ReactiveMongoDatabaseFactory` object that encapsulated the `com.mongodb.reactivestreams.client.MongoClient` object and database name. * `ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc new file mode 100644 index 000000000..093998379 --- /dev/null +++ b/src/main/asciidoc/upgrading.adoc @@ -0,0 +1,123 @@ +[[upgrading]] += Upgrading from 2.x to 3.x + +Spring Data MongoDB 3.x requires the MongoDB Java Driver 4.x. + +The 4.0 MongoDB Java Driver does no longer support certain features that have already been deprecated in one of the last minor versions. +Some of the changes affect the initial setup configuration as well as compile/runtime features. We summarized the most typical changes one might encounter. + +== Dependency Changes + +Instead of the single artifact uber jar `mongo-java-driver`, imports are now split to include separate artifacts: + +* `org.mongodb:mongodb-driver-core` (required) +* `org.mongodb:mongodb-driver-sync` (optional) +* `org.mongodb:mongodb-driver-reactivestreams` (optional) + +== Java Configuration + +.Java API changes +|=== +Type | Comment + +| `MongoClientFactoryBean` +| Creates `com.mongodb.client.MongoClient` instead of `com.mongodb.MongoClient` + +Uses `MongoClientSettings` instead of `MongoClientOptions`. + +| `MongoDataIntegrityViolationException` +| Uses `WriteConcernResult` instead of `WriteResult`. + +| `BulkOperationException` +| Uses `MongoBulkWriteException` and `com.mongodb.bulk.BulkWriteError` instead of `BulkWriteException` and `com.mongodb.BulkWriteError` + +| `ReactiveMongoClientFactoryBean` +| Uses `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` + +| `ReactiveMongoClientSettingsFactoryBean` +| Now produces `com.mongodb.MongoClientSettings` instead of `com.mongodb.async.client.MongoClientSettings` +|=== + +.Removed Java API: +|=== +2.x | Replacement in 3.x | Comment + +| `MongoClientOptionsFactoryBean` +| `MongoClientSettingsFactoryBean` +| Creating a `com.mongodb.MongoClientSettings`. + +| `AbstractMongoConfiguration` +| `AbstractMongoClientConfiguration` + +(Available since 2.1) +| Using `com.mongodb.client.MongoClient`. + +| `MongoDbFactory#getLegacyDb()` +| - +| - + +| `SimpleMongoDbFactory` +| `SimpleMongoClientDbFactory` + +(Available since 2.1) +| + +| `MapReduceOptions#getOutputType()` +| `MapReduceOptions#getMapReduceAction()` +| Returns `MapReduceAction` instead of `MapReduceCommand.OutputType`. + +| `Meta\|Query` maxScan & snapshot +| +| +|=== + +== XML Namespace + +.Changed XML Namespace Elements and Attributes: +|=== +Element / Attribute | 2.x | 3.x + +| `` +| Used to create a `com.mongodb.MongoClient` +| Now exposes a `com.mongodb.client.MongoClient` + +| `` +| Was a comma delimited list of replica set members (host/port) +| Now defines the replica set name. + +Use `` instead + +| `` +| NONE, NORMAL, SAFE, FSYNC_SAFE, REPLICAS_SAFE, MAJORITY +| W1, W2, W3, UNAKNOWLEDGED, AKNOWLEDGED, JOURNALED, MAJORITY +|=== + +.Removed XML Namespace Elements and Attributes: +|=== +Element / Attribute | Replacement in 3.x | Comment + +| `` +| `` +| Referencing a `com.mongodb.client.MongoClient`. + +| `` +| `` +| Single authentication data instead of list. + +| `` +| `` +| See `com.mongodb.MongoClientSettings` for details. +|=== + +.New XML Namespace Elements and Attributes: +|=== +Element | Comment + +| `` +| Replacement for `` + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Replacement for `uri` and `client-uri`. + +| `` +| Namespace element for `com.mongodb.MongoClientSettings`. + +|===