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 e103fd37f..d4ec1f5d8 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 @@ -144,10 +144,12 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp } /** - * Create {@link MongoClientSettings} based on configuration and priority (lower is better).
- * 1. {@link MongoClientFactoryBean#mongoClientSettings}
- * 2. {@link MongoClientFactoryBean#connectionString}
- * 3. default {@link MongoClientSettings} + * Create {@link MongoClientSettings} based on configuration and priority (lower is better). + *
    + *
  1. {@link MongoClientFactoryBean#mongoClientSettings}
  2. + *
  3. {@link MongoClientFactoryBean#connectionString}
  4. + *
  5. default {@link MongoClientSettings}
  6. + *
* * @since 3.0 */ @@ -220,7 +222,7 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp }) // .applyToConnectionPoolSettings(settings -> { - applySettings(it -> settings.maintenanceFrequency(it.longValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.maintenanceFrequency(it, TimeUnit.MILLISECONDS), computeSettingsValue((ConnectionPoolSettings it) -> it.getMaintenanceFrequency(TimeUnit.MILLISECONDS), defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); @@ -239,7 +241,7 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, connectionString.getMaxWaitTime())); - applySettings(it -> settings.maintenanceInitialDelay(it.longValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.maintenanceInitialDelay(it, TimeUnit.MILLISECONDS), computeSettingsValue( (ConnectionPoolSettings it) -> it.getMaintenanceInitialDelay(TimeUnit.MILLISECONDS), defaultSettings.getConnectionPoolSettings(), connectionPoolSettings, null)); @@ -253,11 +255,11 @@ public class MongoClientFactoryBean extends AbstractFactoryBean imp }) // .applyToSocketSettings(settings -> { - applySettings(it -> settings.connectTimeout(it.intValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.connectTimeout(it, TimeUnit.MILLISECONDS), computeSettingsValue((SocketSettings it) -> it.getConnectTimeout(TimeUnit.MILLISECONDS), defaultSettings.getSocketSettings(), socketSettings, connectionString.getConnectTimeout())); - applySettings(it -> settings.readTimeout(it.intValue(), TimeUnit.MILLISECONDS), + applySettings(it -> settings.readTimeout(it, TimeUnit.MILLISECONDS), computeSettingsValue((SocketSettings it) -> it.getReadTimeout(TimeUnit.MILLISECONDS), defaultSettings.getSocketSettings(), socketSettings, connectionString.getSocketTimeout())); applySettings(settings::receiveBufferSize, computeSettingsValue(SocketSettings::getReceiveBufferSize, 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 index e688433b6..f8cf254cb 100644 --- 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 @@ -24,10 +24,10 @@ 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; @@ -45,6 +45,7 @@ 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 + * @author Mark Paluch * @since 3.0 */ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { @@ -65,18 +66,57 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean Socket Settings - private Integer socketConnectTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings() + private int 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(); + private int socketReadTimeoutMS = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS); + private int socketReceiveBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getReceiveBufferSize(); + private int socketSendBufferSize = DEFAULT_MONGO_SETTINGS.getSocketSettings().getSendBufferSize(); + + // --> 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); + + // --> ConnectionPoolSettings + + private int poolMaxSize = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings().getMaxSize(); + private int 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); + + // --> 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() + : ""; + + // encryption and retry + + private @Nullable AutoEncryptionSettings autoEncryptionSettings; /** * @param socketConnectTimeoutMS in msec * @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(int, TimeUnit) */ - public void setSocketConnectTimeoutMS(Integer socketConnectTimeoutMS) { + public void setSocketConnectTimeoutMS(int socketConnectTimeoutMS) { this.socketConnectTimeoutMS = socketConnectTimeoutMS; } @@ -84,7 +124,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean Server Settings - private Long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + private long serverHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() .getHeartbeatFrequency(TimeUnit.MILLISECONDS); - private Long serverMinHeartbeatFrequencyMS = DEFAULT_MONGO_SETTINGS.getServerSettings() + 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) { + public void setServerHeartbeatFrequencyMS(long serverHeartbeatFrequencyMS) { this.serverHeartbeatFrequencyMS = serverHeartbeatFrequencyMS; } @@ -123,23 +163,12 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean 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) @@ -158,7 +187,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean 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) { + public void setPoolMaxSize(int poolMaxSize) { this.poolMaxSize = poolMaxSize; } @@ -225,7 +241,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean 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) @@ -304,8 +314,6 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { settings.serverSelectionTimeout(clusterServerSelectionTimeoutMS, TimeUnit.MILLISECONDS); - if(clusterConnectionMode != null) { + if (clusterConnectionMode != null) { settings.mode(clusterConnectionMode); } settings.requiredReplicaSetName(clusterRequiredReplicaSetName); @@ -405,7 +413,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean { - settings.connectTimeout(socketConnectTimeoutMS.intValue(), TimeUnit.MILLISECONDS); - settings.readTimeout(socketReadTimeoutMS.intValue(), TimeUnit.MILLISECONDS); + settings.connectTimeout(socketConnectTimeoutMS, TimeUnit.MILLISECONDS); + settings.readTimeout(socketReadTimeoutMS, TimeUnit.MILLISECONDS); settings.receiveBufferSize(socketReceiveBufferSize); settings.sendBufferSize(socketSendBufferSize); }) // .applyToSslSettings((settings) -> { settings.enabled(sslEnabled); - if (ObjectUtils.nullSafeEquals(Boolean.TRUE, sslEnabled)) { + if (sslEnabled) { settings.invalidHostNameAllowed(sslInvalidHostNameAllowed); try { - settings.context(StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); + settings.context( + StringUtils.hasText(sslProvider) ? SSLContext.getInstance(sslProvider) : SSLContext.getDefault()); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e.getMessage(), e); } 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 cd441ae24..01a252b80 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 @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core; import static org.springframework.data.mongodb.core.query.SerializationUtils.*; +import com.mongodb.client.MongoClient; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; @@ -213,7 +214,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @param databaseName must not be {@literal null} or empty. * @since 2.1 */ - public MongoTemplate(com.mongodb.client.MongoClient mongoClient, String databaseName) { + public MongoTemplate(MongoClient mongoClient, String databaseName) { this(new SimpleMongoClientDatabaseFactory(mongoClient, databaseName), (MongoConverter) null); } 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 43c3fd737..c62bd5c54 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 @@ -21,6 +21,7 @@ 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 + * @author Christoph Strobl * @since 2.0 * @deprecated since 3.0 - Use {@link MongoClientSettingsFactoryBean} instead. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java index 39ad590d9..5be87b573 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java @@ -23,8 +23,6 @@ import org.springframework.data.mongodb.core.query.Collation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import com.mongodb.DBObject; - /** * Holds a set of configurable aggregation options that can be used within an aggregation pipeline. A list of support * aggregation options can be found in the MongoDB reference documentation @@ -115,7 +113,7 @@ public class AggregationOptions { } /** - * Creates new {@link AggregationOptions} given {@link DBObject} containing aggregation options. + * Creates new {@link AggregationOptions} given {@link Document} containing aggregation options. * * @param document must not be {@literal null}. * @return the {@link AggregationOptions}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java index 596cdd815..7cc656d54 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/PartialIndexFilter.java @@ -26,7 +26,7 @@ import org.springframework.data.mongodb.core.query.CriteriaDefinition; import com.mongodb.DBObject; /** - * {@link IndexFilter} implementation for usage with plain {@link DBObject} as well as {@link CriteriaDefinition} filter + * {@link IndexFilter} implementation for usage with plain {@link Document} as well as {@link CriteriaDefinition} filter * expressions. * * @author Christoph Strobl @@ -38,7 +38,7 @@ public class PartialIndexFilter implements IndexFilter { private final @NonNull Object filterExpression; /** - * Create new {@link PartialIndexFilter} for given {@link DBObject filter expression}. + * Create new {@link PartialIndexFilter} for given {@link Document filter expression}. * * @param where must not be {@literal null}. * @return 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 446feb8e0..0afd09f70 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 @@ -358,7 +358,7 @@ public class MapReduceOptions { } /** - * @return {@literal true} if {@literal inline} output shall is used. + * @return {@literal true} if {@literal inline} output is used. * @since 2.0.10 */ public boolean usesInlineOutput() { diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index af0a45b37..1ebb3098c 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -10,7 +10,8 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.xsd=org/spri http\://www.springframework.org/schema/data/mongo/spring-mongo-1.10.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.10.2.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-2.2.xsd=org/springframework/data/mongodb/config/spring-mongo-2.0.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-2.2.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo-3.0.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-3.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/springframework/data/mongodb/config/spring-mongo-1.0.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd https\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd 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 index c2d5ce6bb..4e6cfcc6b 100644 --- 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 @@ -140,5 +140,4 @@ public class MongoClientNamespaceTests { 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/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index 2824cd89a..5113197cc 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 @@ -204,8 +204,7 @@ public class MongoNamespaceTests { } @Test - @SuppressWarnings("deprecation") - public void testMongoSingletonWithPropertyPlaceHolders() throws Exception { + public void testMongoSingletonWithPropertyPlaceHolders() { assertThat(ctx.containsBean("mongoClient")).isTrue(); MongoClientFactoryBean mfb = (MongoClientFactoryBean) ctx.getBean("&mongoClient"); @@ -215,20 +214,5 @@ public class MongoNamespaceTests { assertThat(host).isEqualTo("127.0.0.1"); assertThat(port).isEqualTo(new Integer(27017)); - - // 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()); - // assertEquals(0, mongoOpts.getWriteConcern().getWtimeout()); - // assertEquals(true, mongoOpts.getWriteConcern().fsync()); } } 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 index fc9e3320f..773f39dc6 100644 --- 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 @@ -1,19 +1,3 @@ -/* - * 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. * @@ -35,13 +19,15 @@ 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; +import com.mongodb.ServerAddress; /** + * Unit tests for {@link MongoClientFactoryBean}. + * * @author Christoph Strobl */ class MongoClientFactoryBeanUnitTests { @@ -95,12 +81,12 @@ class MongoClientFactoryBeanUnitTests { } @Test // DATAMONGO-2427 - void hostAndPortPlusConnectionStringError() throws Exception { + void hostAndPortPlusConnectionStringError() { MongoClientFactoryBean factoryBean = new MongoClientFactoryBean(); factoryBean.setConnectionString(CONNECTION_STRING); factoryBean.setHost("localhost"); factoryBean.setPort(27017); - assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> factoryBean.createInstance()); + assertThatExceptionOfType(IllegalStateException.class).isThrownBy(factoryBean::createInstance); } } 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 index 4b5cf6ddb..ee93abf13 100644 --- 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 @@ -28,7 +28,7 @@ import com.mongodb.ReadConcern; import com.mongodb.ReadPreference; /** - * Integration tests for {@link MongoClientSettingsFactoryBean}. + * Unit tests for {@link MongoClientSettingsFactoryBean}. * * @author Christoph Strobl */ 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 e10be3254..5404d7c00 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 @@ -79,6 +79,7 @@ public class QueryCursorPreparerUnitTests { verify(cursor).hint(new Document("age", 1)); } + // TODO // @Test // DATAMONGO-957 // public void doesNotApplyMetaWhenEmpty() { // @@ -117,6 +118,7 @@ public class QueryCursorPreparerUnitTests { verify(cursor).comment("spring data"); } + // TODO // @Test // DATAMONGO-957 // public void appliesSnapshotCorrectly() { // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java index 89da5de00..794e40794 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java @@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; -import static org.springframework.test.util.ReflectionTestUtils.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; @@ -26,6 +25,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; + import org.springframework.aop.framework.AopProxyUtils; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.test.util.ReflectionTestUtils; @@ -61,7 +61,6 @@ public class SimpleMongoClientDatabaseFactoryUnitTests { } @Test // DATADOC-254 - @SuppressWarnings("deprecation") public void allowsDatabaseNames() { new SimpleMongoClientDatabaseFactory(mongo, "foo-bar"); new SimpleMongoClientDatabaseFactory(mongo, "foo_bar"); @@ -69,14 +68,13 @@ public class SimpleMongoClientDatabaseFactoryUnitTests { } @Test // DATADOC-295 - @SuppressWarnings("deprecation") public void mongoUriConstructor() { ConnectionString mongoURI = new ConnectionString( "mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); MongoDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(mongoURI); - assertThat(getField(mongoDbFactory, "databaseName").toString()).isEqualTo("myDatabase"); + assertThat(mongoDbFactory).hasFieldOrPropertyWithValue("databaseName", "myDatabase"); } @Test // DATAMONGO-1158 @@ -86,7 +84,7 @@ public class SimpleMongoClientDatabaseFactoryUnitTests { "mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection"); SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(uri); - assertThat(getField(factory, "databaseName").toString()).isEqualTo("myDataBase"); + assertThat(factory).hasFieldOrPropertyWithValue("databaseName", "myDataBase"); } @Test // DATAMONGO-1880 diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 9b0a3d1ae..afa253e62 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -4,6 +4,7 @@ [[new-features.3.0]] == What's New in Spring Data MongoDB 3.0 +* Upgrade to MongoDB Driver 4.0. See <> for further details. * Support for <>. * Removal of `_id` flattening for composite Id's when using `MongoTemplate` aggregations. * Apply pagination when using GridFS `find(Query)`. diff --git a/src/main/asciidoc/preface.adoc b/src/main/asciidoc/preface.adoc index 448eb5414..cd1a397a3 100644 --- a/src/main/asciidoc/preface.adoc +++ b/src/main/asciidoc/preface.adoc @@ -39,20 +39,23 @@ The starting point for learning about MongoDB is https://www.mongodb.org/[www.mo [[requirements]] == Requirements -The Spring Data MongoDB 2.x binaries require JDK level 8.0 and above and https://spring.io/docs[Spring Framework] {springVersion} and above. +The Spring Data MongoDB 3.x binaries require JDK level 8.0 and above and https://spring.io/docs[Spring Framework] {springVersion} and above. In terms of document stores, you need at least version 2.6 of https://www.mongodb.org/[MongoDB]. [[get-started:help]] == Additional Help Resources -Learning a new framework is not always straightforward. In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data MongoDB module. However, if you encounter issues or you need advice, feel free to use one of the following links: +Learning a new framework is not always straightforward. +In this section, we try to provide what we think is an easy-to-follow guide for starting with the Spring Data MongoDB module. +However, if you encounter issues or you need advice, feel free to use one of the following links: [[get-started:help:community]] -Community Forum :: Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all Spring Data (not just Document) users to share information and help each other. Note that registration is needed only for posting. +Community Forum :: Spring Data on https://stackoverflow.com/questions/tagged/spring-data[Stack Overflow] is a tag for all Spring Data (not just Document) users to share information and help each other. +Note that registration is needed only for posting. [[get-started:help:professional]] -Professional Support :: Professional, from-the-source support, with guaranteed response time, is available from https://pivotal.io/[Pivotal Sofware, Inc.], the company behind Spring Data and Spring. +Professional Support :: Professional, from-the-source support, with guaranteed response time, is available from https://pivotal.io/[Pivotal Software, Inc.], the company behind Spring Data and Spring. [[get-started:up-to-date]] == Following Development diff --git a/src/main/asciidoc/reference/client-session-transactions.adoc b/src/main/asciidoc/reference/client-session-transactions.adoc index 6343ae54e..490ae8d19 100644 --- a/src/main/asciidoc/reference/client-session-transactions.adoc +++ b/src/main/asciidoc/reference/client-session-transactions.adoc @@ -185,10 +185,10 @@ The `MongoTransactionManager` binds a `ClientSession` to the thread. `MongoTempl [source,java] ---- @Configuration -static class Config extends AbstractMongoConfiguration { +static class Config extends AbstractMongoClientConfiguration { @Bean - MongoTransactionManager transactionManager(MongoDbFactory dbFactory) { <1> + MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { <1> return new MongoTransactionManager(dbFactory); } @@ -199,7 +199,7 @@ static class Config extends AbstractMongoConfiguration { public class StateService { @Transactional - void someBusinessFunction(Step step) { <2> + void someBusinessFunction(Step step) { <2> template.insert(step); diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc index 8aed43238..b034cdf67 100644 --- a/src/main/asciidoc/reference/mapping.adoc +++ b/src/main/asciidoc/reference/mapping.adoc @@ -278,7 +278,6 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration { // the following are optional - @Bean @Override public CustomConversions customConversions() throws Exception { @@ -311,10 +310,9 @@ Spring's MongoDB namespace lets you enable mapping functionality in XML, as the @@ -769,7 +767,7 @@ To selectively handle the conversion yourself, register one or more one or more NOTE: Spring 3.0 introduced a core.convert package that provides a general type conversion system. This is described in detail in the Spring reference documentation section entitled https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/core.html#validation["`Spring Type Conversion`"]. -You can use the `customConversions` method in `AbstractMongoConfiguration` to configure converters. The examples <> show how to perform the configuration using Java and XML. +You can use the `customConversions` method in `AbstractMongoClientConfiguration` to configure converters. The examples <> show how to perform the configuration using Java and XML. The following example of a Spring Converter implementation converts from a `Document` to a `Person` POJO: diff --git a/src/main/asciidoc/reference/migrating.adoc b/src/main/asciidoc/reference/migrating.adoc index 81cfb0780..0a8298487 100644 --- a/src/main/asciidoc/reference/migrating.adoc +++ b/src/main/asciidoc/reference/migrating.adoc @@ -13,8 +13,7 @@ This chapter coverts major changes and outlines migration steps. ** core-jar ** sync-jar - -This allows to include eg. just the reactive bits without having to pull in all the sync stuff. +The change in dependencies allows usage of the reactive support without having to pull the synchronous driver. NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please use `org.bson.Document` instead. === Signature Changes @@ -22,7 +21,7 @@ NOTE: The new sync driver does no longer support `com.mongodb.DBObject`. Please * `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`. +In case you're using `AbstractMongoConfiguration` please switch to `AbstractMongoClientConfiguration`. === Namespace Changes diff --git a/src/main/asciidoc/reference/mongo-3.adoc b/src/main/asciidoc/reference/mongo-3.adoc index 04cc265fa..2952edf47 100644 --- a/src/main/asciidoc/reference/mongo-3.adoc +++ b/src/main/asciidoc/reference/mongo-3.adoc @@ -1,12 +1,10 @@ [[mongo.mongo-3]] = MongoDB 3.0 Support -Spring Data MongoDB requires MongoDB Java driver generations 3 when connecting to a MongoDB 2.6/3.0 server running MMap.v1 or a MongoDB server 3.0 using MMap.v1 or the WiredTiger storage engine. +Spring Data MongoDB requires MongoDB Java driver generations 4 when connecting to a MongoDB 2.6/3.0 server running MMap.v1 or a MongoDB server 3.0 using MMap.v1 or the WiredTiger storage engine. NOTE: See the driver- and database-specific documentation for major differences between those engines. -NOTE: Operations that are no longer valid when using a 3.x MongoDB Java driver have been deprecated within Spring Data and will be removed in a subsequent release. - == Using Spring Data MongoDB with MongoDB 3.0 The rest of this section describes how to use Spring Data MongoDB with MongoDB 3.0. @@ -51,7 +49,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() { @@ -118,11 +116,12 @@ NOTE: The field names used within the query expression are mapped to the domain [[mongo.mongo-3.misc]] === Miscellaneous Details -This section covers briefly lists additional things to keep in mind when using the 3.0 driver: +This section covers briefly lists additional things to keep in mind when using the 4.0 driver: * `IndexOperations.resetIndexCache()` is no longer supported. * Any `MapReduceOptions.extraOption` is silently ignored. * `WriteResult` no longer holds error information but, instead, throws an `Exception`. * `MongoOperations.executeInSession(…)` no longer calls `requestStart` and `requestDone`. -* Index name generation has become a driver-internal operation. Spring Data MongoDB still uses the 2.x schema to generate names. +* Index name generation has become a driver-internal operation. +Spring Data MongoDB still uses the 2.x schema to generate names. * Some `Exception` messages differ between the generation 2 and 3 servers as well as between the MMap.v1 and WiredTiger storage engines. diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc index a97ccf93b..00f1493b6 100644 --- a/src/main/asciidoc/reference/mongo-repositories.adoc +++ b/src/main/asciidoc/reference/mongo-repositories.adoc @@ -112,7 +112,7 @@ Because our domain repository extends `PagingAndSortingRepository`, it provides ==== [source,java] ---- -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class PersonRepositoryTests { @@ -601,7 +601,7 @@ class MongoTemplateProducer { @ApplicationScoped public MongoOperations createMongoTemplate() { - MongoDbFactory factory = new SimpleMongoClientDbFactory(MongoClients.create(), "database"); + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"); return new MongoTemplate(factory); } } diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index b2d08d453..7d849dfe1 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -165,7 +165,7 @@ 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.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. +One of the first tasks when using MongoDB and Spring is to create a `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]. @@ -230,11 +230,9 @@ To use the Mongo namespace elements, you need to reference the Mongo schema, as @@ -281,21 +279,21 @@ The following example shows a configuration using replica sets: ==== [[mongo.mongo-db-factory]] -=== The MongoDbFactory Interface +=== The MongoDatabaseFactory Interface -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: +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.MongoDatabaseFactory` interface, shown in the following listing, to bootstrap connectivity to the database: [source,java] ---- -public interface MongoDbFactory { +public interface MongoDatabaseFactory { - MongoDatabase getDb() throws DataAccessException; + MongoDatabase getDatabase() throws DataAccessException; - MongoDatabase getDb(String dbName) throws DataAccessException; + MongoDatabase getDatabase(String dbName) throws DataAccessException; } ---- -The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the `MongoDbFactory` interface. In turn, you can use the `MongoDbFactory` instance to configure `MongoTemplate`. +The following sections show how you can use the container with either Java-based or XML-based metadata to configure an instance of the `MongoDatabaseFactory` interface. In turn, you can use the `MongoDatabaseFactory` instance to configure `MongoTemplate`. Instead of using the IoC container to create an instance of MongoTemplate, you can use them in standard Java code, as follows: @@ -307,7 +305,7 @@ public class MongoApp { public static void main(String[] args) throws Exception { - MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDbFactory(MongoClients.create(), "database")); + MongoOperations mongoOps = new MongoTemplate(new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database")); mongoOps.insert(new Person("Joe", 34)); @@ -323,17 +321,17 @@ The code in bold highlights the use of `SimpleMongoClientDbFactory` and is the o NOTE: Use `SimpleMongoClientDbFactory` when choosing `com.mongodb.client.MongoClient` as the entrypoint of choice. [[mongo.mongo-db-factory-java]] -=== Registering a `MongoDbFactory` Instance by Using Java-based Metadata +=== Registering a `MongoDatabaseFactory` Instance by Using Java-based Metadata -To register a `MongoDbFactory` instance with the container, you write code much like what was highlighted in the previous code listing. The following listing shows a simple example: +To register a `MongoDatabaseFactory` instance with the container, you write code much like what was highlighted in the previous code listing. The following listing shows a simple example: [source,java] ---- @Configuration public class MongoConfiguration { - public @Bean MongoDbFactory mongoDbFactory() { - return new SimpleMongoClientDbFactory(MongoClients.create(), "database"); + public @Bean MongoDatabaseFactory mongoDatabaseFactory() { + return new SimpleMongoClientDatabaseFactory(MongoClients.create(), "database"); } } ---- @@ -391,7 +389,7 @@ public class MongoClientConfiguration extends AbstractMongoClientConfiguration { ---- [[mongo.mongo-db-factory-xml]] -=== Registering a `MongoDbFactory` Instance by Using XML-based Metadata +=== Registering a `MongoDatabaseFactory` Instance by Using XML-based Metadata The `mongo` namespace provides a convenient way to create a `SimpleMongoClientDbFactory`, as compared to using the `` namespace, as shown in the following example: @@ -470,12 +468,12 @@ public class AppConfig { There are several overloaded constructors of `MongoTemplate`: * `MongoTemplate(MongoClient mongo, String databaseName)`: Takes the `MongoClient` object and the default database name to operate against. -* `MongoTemplate(MongoDbFactory mongoDbFactory)`: Takes a MongoDbFactory object that encapsulated the `MongoClient` object, database name, and username and password. -* `MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. +* `MongoTemplate(MongoDatabaseFactory mongoDbFactory)`: Takes a MongoDbFactory object that encapsulated the `MongoClient` object, database name, and username and password. +* `MongoTemplate(MongoDatabaseFactory mongoDbFactory, MongoConverter mongoConverter)`: Adds a `MongoConverter` to use for mapping. You can also configure a MongoTemplate by using Spring's XML schema, as the following example shows: -[source,java] +[source,xml] ---- @@ -3270,7 +3268,7 @@ boolean hasIndex = template.execute("geolocation", new CollectionCallbackBoolean [[gridfs]] == GridFS Support -MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDbFactory` as well as a `MongoConverter`, as the following example shows: +MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a `GridFsOperations` interface as well as the corresponding implementation, `GridFsTemplate`, to let you interact with the filesystem. You can set up a `GridFsTemplate` instance by handing it a `MongoDatabaseFactory` as well as a `MongoConverter`, as the following example shows: .JavaConfig setup for a GridFsTemplate ==== diff --git a/src/main/asciidoc/upgrading.adoc b/src/main/asciidoc/upgrading.adoc index 4006d1d3a..507790132 100644 --- a/src/main/asciidoc/upgrading.adoc +++ b/src/main/asciidoc/upgrading.adoc @@ -1,4 +1,4 @@ -[[upgrading]] +[[upgrading.2-3]] = Upgrading from 2.x to 3.x Spring Data MongoDB 3.x requires the MongoDB Java Driver 4.x. +