DATAMONGO-1968 - Polishing.

Rename MongoDbFactoryBase to MongoDbFactorySupport. Add constructor to MongoTemplate accepting the new MongoClient type. Extend Javadoc. Switch tests to use the new MongoTemplate constructor.

Original pull request: #557.
This commit is contained in:
Mark Paluch
2018-05-11 10:11:57 +02:00
parent 5470486d8d
commit 85aef4836d
10 changed files with 127 additions and 32 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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.
* <p/>
* Not intended to be used directly.
*
* @author Christoph Strobl
* @author Mark Paluch
* @param <C> Client type.
* @since 2.1
* @see SimpleMongoDbFactory
* @see SimpleMongoClientDbFactory
*/
abstract class MongoDbFactoryBase<T> implements MongoDbFactory {
public abstract class MongoDbFactorySupport<C> 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<T> 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<T> 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<T> 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<T> 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<T> 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);
}

View File

@@ -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.

View File

@@ -31,12 +31,13 @@ import com.mongodb.client.MongoDatabase;
* @author Christoph Strobl
* @since 2.1
*/
public class SimpleMongoClientDbFactory extends MongoDbFactoryBase<MongoClient> implements DisposableBean {
public class SimpleMongoClientDbFactory extends MongoDbFactorySupport<MongoClient> 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 <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Connection String reference</a>
*/
public SimpleMongoClientDbFactory(String connectionString) {
@@ -46,7 +47,8 @@ public class SimpleMongoClientDbFactory extends MongoDbFactoryBase<MongoClient>
/**
* 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<MongoClient>
* 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<MongoClient>
* 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<MongoClient>
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));
}

View File

@@ -36,12 +36,12 @@ import com.mongodb.client.MongoDatabase;
* @author George Moraitis
* @author Mark Paluch
*/
public class SimpleMongoDbFactory extends MongoDbFactoryBase<MongoClient> implements DisposableBean {
public class SimpleMongoDbFactory extends MongoDbFactorySupport<MongoClient> 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<MongoClient> 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<MongoClient> 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<MongoClient> 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);

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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]
----