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 41688f1a4..2daadb7ca 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 @@ -33,8 +33,9 @@ import com.mongodb.client.MongoClient; * Base class for Spring Data MongoDB configuration using JavaConfig with {@link com.mongodb.client.MongoClient}. * * @author Christoph Strobl - * @see MongoConfigurationSupport * @since 2.1 + * @see MongoConfigurationSupport + * @see AbstractMongoConfiguration */ @Configuration public abstract class AbstractMongoClientConfiguration extends MongoConfigurationSupport { 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 index e12041ccc..b4b8d4717 100644 --- 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 @@ -41,6 +41,7 @@ import com.mongodb.MongoClient; * @author Christoph Strobl * @author Mark Paluch * @see MongoConfigurationSupport + * @see AbstractMongoClientConfiguration */ @Configuration public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactoryBase.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java similarity index 78% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactoryBase.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java index 86d6ff862..1aa8254f8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactoryBase.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDbFactorySupport.java @@ -33,21 +33,38 @@ 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}. + * 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. + *

+ * Not intended to be used directly. * * @author Christoph Strobl + * @author Mark Paluch + * @param Client type. * @since 2.1 + * @see SimpleMongoDbFactory + * @see SimpleMongoClientDbFactory */ -abstract class MongoDbFactoryBase implements MongoDbFactory { +public abstract class MongoDbFactorySupport implements MongoDbFactory { - private final T mongoClient; + private final C mongoClient; private final String databaseName; private final boolean mongoInstanceCreated; private final PersistenceExceptionTranslator exceptionTranslator; private @Nullable WriteConcern writeConcern; - protected MongoDbFactoryBase(T mongoClient, String databaseName, boolean mongoInstanceCreated, + /** + * Create a new {@link MongoDbFactorySupport} object given {@code mongoClient}, {@code databaseName}, + * {@code mongoInstanceCreated} and {@link PersistenceExceptionTranslator}. + * + * @param mongoClient must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. + * @param mongoInstanceCreated {@literal true} if the client instance was created by a subclass of + * {@link MongoDbFactorySupport} to close the client on {@link #destroy()}. + * @param exceptionTranslator must not be {@literal null}. + */ + protected MongoDbFactorySupport(C mongoClient, String databaseName, boolean mongoInstanceCreated, PersistenceExceptionTranslator exceptionTranslator) { Assert.notNull(mongoClient, "MongoClient must not be null!"); @@ -62,7 +79,7 @@ abstract class MongoDbFactoryBase implements MongoDbFactory { } /** - * Configures the {@link WriteConcern} to be used on the {@link DB} instance being created. + * Configures the {@link WriteConcern} to be used on the {@link MongoDatabase} instance being created. * * @param writeConcern the writeConcern to set */ @@ -85,7 +102,7 @@ abstract class MongoDbFactoryBase implements MongoDbFactory { @Override public MongoDatabase getDb(String dbName) throws DataAccessException { - Assert.hasText(dbName, "Database name must not be empty."); + Assert.hasText(dbName, "Database name must not be empty!"); MongoDatabase db = doGetMongoDatabase(dbName); @@ -96,6 +113,18 @@ abstract class MongoDbFactoryBase implements MongoDbFactory { return db.withWriteConcern(writeConcern); } + /** + * Get the actual {@link MongoDatabase} from the client. + * + * @param dbName must not be {@literal null} or empty. + * @return + */ + protected abstract MongoDatabase doGetMongoDatabase(String dbName); + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ public void destroy() throws Exception { if (mongoInstanceCreated) { closeClient(); @@ -115,17 +144,24 @@ abstract class MongoDbFactoryBase implements MongoDbFactory { * @see org.springframework.data.mongodb.MongoDbFactory#withSession(com.mongodb.session.Session) */ public MongoDbFactory withSession(ClientSession session) { - return new MongoDbFactoryBase.ClientSessionBoundMongoDbFactory(session, this); + return new MongoDbFactorySupport.ClientSessionBoundMongoDbFactory(session, this); } + /** + * Close the client instance. + */ protected abstract void closeClient(); - protected abstract MongoDatabase doGetMongoDatabase(String dbName); - - protected T getMongoClient() { + /** + * @return the Mongo client object. + */ + protected C getMongoClient() { return mongoClient; } + /** + * @return the database name. + */ protected String getDefaultDatabaseName() { return databaseName; } @@ -205,7 +241,7 @@ abstract class MongoDbFactoryBase implements MongoDbFactory { return createProxyInstance(session, database, MongoDatabase.class); } - private MongoCollection proxyCollection(com.mongodb.session.ClientSession session, MongoCollection collection) { + private MongoCollection proxyCollection(com.mongodb.session.ClientSession session, MongoCollection collection) { return createProxyInstance(session, collection, MongoCollection.class); } 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 78c0722e5..62e2bf8ed 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 @@ -210,7 +210,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, private SessionSynchronization sessionSynchronization = SessionSynchronization.ON_ACTUAL_TRANSACTION; /** - * Constructor used for a basic template configuration + * Constructor used for a basic template configuration. * * @param mongoClient must not be {@literal null}. * @param databaseName must not be {@literal null} or empty. @@ -218,6 +218,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, public MongoTemplate(MongoClient mongoClient, String databaseName) { this(new SimpleMongoDbFactory(mongoClient, databaseName), (MongoConverter) null); } + + /** + * Constructor used for a basic template configuration. + * + * @param mongoClient must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. + * @since 2.1 + */ + public MongoTemplate(com.mongodb.client.MongoClient mongoClient, String databaseName) { + this(new SimpleMongoClientDbFactory(mongoClient, databaseName), (MongoConverter) null); + } /** * Constructor used for a basic template configuration. 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 f03980957..bec369b90 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 @@ -31,12 +31,13 @@ import com.mongodb.client.MongoDatabase; * @author Christoph Strobl * @since 2.1 */ -public class SimpleMongoClientDbFactory extends MongoDbFactoryBase implements DisposableBean { +public class SimpleMongoClientDbFactory extends MongoDbFactorySupport implements DisposableBean { /** * Creates a new {@link SimpleMongoClientDbFactory} instance for the given {@code connectionString}. * - * @param connectionString must not be {@literal null}. + * @param connectionString connection coordinates for a database connection. Must contain a database name and must not + * be {@literal null} or empty. * @see MongoDB Connection String reference */ public SimpleMongoClientDbFactory(String connectionString) { @@ -46,7 +47,8 @@ public class SimpleMongoClientDbFactory extends MongoDbFactoryBase /** * Creates a new {@link SimpleMongoClientDbFactory} instance from the given {@link MongoClient}. * - * @param connectionString must not be {@literal null}. + * @param connectionString connection coordinates for a database connection. Must contain also a database name and not + * be {@literal null}. */ public SimpleMongoClientDbFactory(ConnectionString connectionString) { this(MongoClients.create(connectionString), connectionString.getDatabase(), true); @@ -56,7 +58,7 @@ public class SimpleMongoClientDbFactory extends MongoDbFactoryBase * Creates a new {@link SimpleMongoClientDbFactory} instance from the given {@link MongoClient}. * * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. */ public SimpleMongoClientDbFactory(MongoClient mongoClient, String databaseName) { this(mongoClient, databaseName, false); @@ -66,7 +68,7 @@ public class SimpleMongoClientDbFactory extends MongoDbFactoryBase * Creates a new {@link SimpleMongoClientDbFactory} instance from the given {@link MongoClient}. * * @param mongoClient must not be {@literal null}. - * @param databaseName must not be {@literal null}. + * @param databaseName must not be {@literal null} or empty. * @param mongoInstanceCreated */ private SimpleMongoClientDbFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { @@ -81,7 +83,7 @@ public class SimpleMongoClientDbFactory extends MongoDbFactoryBase public DB getLegacyDb() { throw new UnsupportedOperationException(String.format( - "%s does not support legacy DBObject API! Please " + "consider using SimpleMongoDbFactory for that purpose.", + "%s does not support legacy DBObject API! Please consider using SimpleMongoDbFactory for that purpose.", MongoClient.class)); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java index 2e6eb1cd6..2d1d6f2ec 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java @@ -36,12 +36,12 @@ import com.mongodb.client.MongoDatabase; * @author George Moraitis * @author Mark Paluch */ -public class SimpleMongoDbFactory extends MongoDbFactoryBase implements DisposableBean { +public class SimpleMongoDbFactory extends MongoDbFactorySupport implements DisposableBean { /** * Creates a new {@link SimpleMongoDbFactory} instance from the given {@link MongoClientURI}. * - * @param uri must not be {@literal null}. + * @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) { @@ -52,7 +52,7 @@ public class SimpleMongoDbFactory extends MongoDbFactoryBase implem * 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}. + * @param databaseName must not be {@literal null} or empty. * @since 1.7 */ public SimpleMongoDbFactory(MongoClient mongoClient, String databaseName) { @@ -69,6 +69,10 @@ public class SimpleMongoDbFactory extends MongoDbFactoryBase implem super(mongoClient, databaseName, mongoInstanceCreated, new MongoExceptionTranslator()); } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getLegacyDb() + */ @Override public DB getLegacyDb() { return getMongoClient().getDB(getDefaultDatabaseName()); @@ -83,11 +87,19 @@ public class SimpleMongoDbFactory extends MongoDbFactoryBase implem 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/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java index c74697f21..95d43ba61 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ClientSessionTests.java @@ -19,10 +19,12 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import com.mongodb.MongoClient; import lombok.AllArgsConstructor; import lombok.Data; import org.bson.Document; +import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -37,7 +39,6 @@ import org.springframework.data.mongodb.test.util.ReplicaSet; import org.springframework.data.util.Version; import com.mongodb.ClientSessionOptions; -import com.mongodb.MongoClient; import com.mongodb.client.ClientSession; /** @@ -66,6 +67,11 @@ public class ClientSessionTests { template.getDb().getCollection(COLLECTION_NAME).insertOne(new Document("_id", "id-1").append("value", "spring")); } + @After + public void tearDown() { + client.close(); + } + @Test // DATAMONGO-1880 public void shouldApplyClientSession() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java index b7eef7e29..90ba97c28 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java @@ -23,7 +23,9 @@ import static org.springframework.data.mongodb.core.schema.JsonSchemaProperty.*; import lombok.Data; import reactor.test.StepVerifier; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.springframework.data.annotation.Id; @@ -32,11 +34,13 @@ import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.Version; -import com.mongodb.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; + /** * @author Christoph Strobl + * @author Mark Paluch */ public class JsonSchemaQueryTests { @@ -44,13 +48,19 @@ public class JsonSchemaQueryTests { public static @ClassRule MongoVersionRule REQUIRES_AT_LEAST_3_6_0 = MongoVersionRule.atLeast(Version.parse("3.6.0")); + static MongoClient client = MongoClients.create(); MongoTemplate template; Person jellyBelly, roseSpringHeart, kazmardBoombub; + @BeforeClass + public static void beforeClass() { + client = MongoClients.create(); + } + @Before public void setUp() { - template = new MongoTemplate(new MongoClient(), DATABASE_NAME); + template = new MongoTemplate(client, DATABASE_NAME); jellyBelly = new Person(); jellyBelly.id = "1"; @@ -80,6 +90,13 @@ public class JsonSchemaQueryTests { template.save(roseSpringHeart); template.save(kazmardBoombub); } + + @AfterClass + public static void afterClass() { + if (client != null) { + client.close(); + } + } @Test // DATAMONGO-1835 public void findsDocumentsWithRequiredFieldsCorrectly() { @@ -95,8 +112,12 @@ public class JsonSchemaQueryTests { MongoJsonSchema schema = MongoJsonSchema.builder().required("address").build(); - StepVerifier.create(new ReactiveMongoTemplate(MongoClients.create(), DATABASE_NAME) + com.mongodb.reactivestreams.client.MongoClient mongoClient = com.mongodb.reactivestreams.client.MongoClients.create(); + + StepVerifier.create(new ReactiveMongoTemplate(mongoClient, DATABASE_NAME) .find(query(matchingDocumentStructure(schema)), Person.class)).expectNextCount(2).verifyComplete(); + + mongoClient.close(); } @Test // DATAMONGO-1835 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 ccee9a1bc..8bdaf46ff 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 @@ -161,9 +161,14 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { new MongoTemplate(mongo, null); } - @Test(expected = IllegalArgumentException.class) - public void rejectsNullMongo() throws Exception { - new MongoTemplate(null, "database"); + @Test(expected = IllegalArgumentException.class) // DATAMONGO-1968 + public void rejectsNullMongo() { + new MongoTemplate((MongoClient) null, "database"); + } + + @Test(expected = IllegalArgumentException.class) // DATAMONGO-1968 + public void rejectsNullMongoClient() { + new MongoTemplate((com.mongodb.client.MongoClient) null, "database"); } @Test(expected = IllegalArgumentException.class) // DATAMONGO-1870 diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 653e32a95..874c1883c 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -369,8 +369,8 @@ See https://tools.ietf.org/html/rfc3986#section-2.2[section 2.2 of RFC 3986] for As of MongoDB java driver 3.7.0 there is an alternative entry point to `MongoClient` via the http://search.maven .org/#search%7Cgav%7C1%7Cg%3A%22org.mongodb%22%20AND%20a%3A%22mongodb-driver-sync%22[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 may use `AbstractMongoClientConfiguration` to leverage the new `MongoClients` builder API. +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] ----