Browse Source

Introduce factory methods for MongoDatabaseFactory for client lifecycle guidance.

We now expose create(…) methods returning either MongoDatabaseFactory when created with a client that doesn't publicly declare a destroy() method and create methods returning SimpleMongoClientDatabaseFactory when used with a connection string to indicate lifecycle-awareness for the internally created MongoClient.

See #5012
pull/5026/head
Mark Paluch 5 months ago
parent
commit
04d0d94244
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 51
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java
  2. 2
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java
  3. 50
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java
  4. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java
  5. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java
  6. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java
  7. 43
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/observability/TestConfig.java

51
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDatabaseFactory.java

@ -16,12 +16,17 @@ @@ -16,12 +16,17 @@
package org.springframework.data.mongodb;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.util.Assert;
import com.mongodb.ClientSessionOptions;
import com.mongodb.ConnectionString;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoDatabase;
/**
@ -30,10 +35,56 @@ import com.mongodb.client.MongoDatabase; @@ -30,10 +35,56 @@ import com.mongodb.client.MongoDatabase;
* @author Mark Pollack
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
* @since 3.0
*/
public interface MongoDatabaseFactory extends CodecRegistryProvider, MongoSessionProvider {
/**
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance for the given {@code connectionString}. Using this
* factory method will create a new {@link MongoClient} instance that will be closed when calling
* {@link SimpleMongoClientDatabaseFactory#destroy()}.
*
* @param connectionString connection coordinates for a database connection. Must contain a database name and must not
* be {@literal null} or empty.
* @since 4.5.2
* @see <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Connection String reference</a>
*/
static SimpleMongoClientDatabaseFactory create(String connectionString) {
Assert.notNull(connectionString, "ConnectionString must not be null");
return new SimpleMongoClientDatabaseFactory(connectionString);
}
/**
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. Using this
* factory will create a new {@link MongoClient} instance that will be closed when calling
* {@link SimpleMongoClientDatabaseFactory#destroy()}.
*
* @param connectionString connection coordinates for a database connection. Must contain also a database name and not
* be {@literal null}.
* @since 4.5.2
*/
static SimpleMongoClientDatabaseFactory create(ConnectionString connectionString) {
Assert.notNull(connectionString, "ConnectionString must not be null");
return new SimpleMongoClientDatabaseFactory(connectionString);
}
/**
* Creates a new {@link MongoDatabaseFactory} instance from the given {@link MongoClient}. We assume a managed client
* instance that will be disposed by you (or the application container) once the client is no longer required for use.
*
* @param mongoClient must not be {@literal null}.
* @param databaseName must not be {@literal null} or empty.
* @since 4.5.2
*/
static MongoDatabaseFactory create(MongoClient mongoClient, String databaseName) {
return new SimpleMongoClientDatabaseFactory(mongoClient, databaseName);
}
/**
* Obtain a {@link MongoDatabase} from the underlying factory.
*

2
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoSessionProvider.java

@ -31,7 +31,7 @@ import com.mongodb.client.ClientSession; @@ -31,7 +31,7 @@ import com.mongodb.client.ClientSession;
public interface MongoSessionProvider {
/**
* Obtain a {@link ClientSession} with with given options.
* Obtain a {@link ClientSession} with given options.
*
* @param options must not be {@literal null}.
* @return never {@literal null}.

50
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/ReactiveMongoDatabaseFactory.java

@ -18,12 +18,17 @@ package org.springframework.data.mongodb; @@ -18,12 +18,17 @@ package org.springframework.data.mongodb;
import reactor.core.publisher.Mono;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.util.Assert;
import com.mongodb.ClientSessionOptions;
import com.mongodb.ConnectionString;
import com.mongodb.reactivestreams.client.ClientSession;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoDatabase;
/**
@ -36,6 +41,51 @@ import com.mongodb.reactivestreams.client.MongoDatabase; @@ -36,6 +41,51 @@ import com.mongodb.reactivestreams.client.MongoDatabase;
*/
public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
/**
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance for the given {@code connectionString}. Using
* this factory method will create a new {@link MongoClient} instance that will be closed when calling
* {@link SimpleReactiveMongoDatabaseFactory#destroy()}.
*
* @param connectionString connection coordinates for a database connection. Must contain a database name and must not
* be {@literal null} or empty.
* @since 4.5.2
* @see <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Connection String reference</a>
*/
static SimpleReactiveMongoDatabaseFactory create(String connectionString) {
Assert.notNull(connectionString, "ConnectionString must not be null");
return create(new ConnectionString(connectionString));
}
/**
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link MongoClient}. Using this
* factory will create a new {@link MongoClient} instance that will be closed when calling
* {@link SimpleReactiveMongoDatabaseFactory#destroy()}.
*
* @param connectionString connection coordinates for a database connection. Must contain also a database name and not
* be {@literal null}.
* @since 4.5.2
*/
static SimpleReactiveMongoDatabaseFactory create(ConnectionString connectionString) {
Assert.notNull(connectionString, "ConnectionString must not be null");
return new SimpleReactiveMongoDatabaseFactory(connectionString);
}
/**
* Creates a new {@link MongoDatabaseFactory} instance from the given {@link MongoClient}. We assume a managed client
* instance that will be disposed by you (or the application container) once the client is no longer required for use.
*
* @param mongoClient must not be {@literal null}.
* @param databaseName must not be {@literal null} or empty.
* @since 4.5.2
*/
static ReactiveMongoDatabaseFactory create(MongoClient mongoClient, String databaseName) {
return new SimpleReactiveMongoDatabaseFactory(mongoClient, databaseName);
}
/**
* Creates a default {@link MongoDatabase} instance.
*

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoClientConfiguration.java

@ -20,7 +20,6 @@ import org.springframework.context.annotation.Configuration; @@ -20,7 +20,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.SpringDataMongoDB;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@ -75,7 +74,7 @@ public abstract class AbstractMongoClientConfiguration extends MongoConfiguratio @@ -75,7 +74,7 @@ public abstract class AbstractMongoClientConfiguration extends MongoConfiguratio
*/
@Bean
public MongoDatabaseFactory mongoDbFactory() {
return new SimpleMongoClientDatabaseFactory(mongoClient(), getDatabaseName());
return MongoDatabaseFactory.create(mongoClient(), getDatabaseName());
}
/**

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractReactiveMongoConfiguration.java

@ -21,7 +21,6 @@ import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.SpringDataMongoDB;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
@ -79,7 +78,7 @@ public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurat @@ -79,7 +78,7 @@ public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurat
*/
@Bean
public ReactiveMongoDatabaseFactory reactiveMongoDbFactory() {
return new SimpleReactiveMongoDatabaseFactory(reactiveMongoClient(), getDatabaseName());
return ReactiveMongoDatabaseFactory.create(reactiveMongoClient(), getDatabaseName());
}
/**

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactoryUnitTests.java

@ -72,7 +72,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests { @@ -72,7 +72,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests {
ConnectionString mongoURI = new ConnectionString(
"mongodb://myUsername:myPassword@localhost/myDatabase.myCollection");
MongoDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(mongoURI);
SimpleMongoClientDatabaseFactory mongoDbFactory = MongoDatabaseFactory.create(mongoURI);
assertThat(mongoDbFactory).hasFieldOrPropertyWithValue("databaseName", "myDatabase");
}
@ -82,7 +82,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests { @@ -82,7 +82,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests {
ConnectionString uri = new ConnectionString(
"mongodb://myUserName:myPassWord@127.0.0.1:27017/myDataBase.myCollection");
SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(uri);
SimpleMongoClientDatabaseFactory factory = MongoDatabaseFactory.create(uri);
assertThat(factory).hasFieldOrPropertyWithValue("databaseName", "myDataBase");
}
@ -92,7 +92,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests { @@ -92,7 +92,7 @@ class SimpleMongoClientDatabaseFactoryUnitTests {
when(mongo.getDatabase("foo")).thenReturn(database);
MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(mongo, "foo");
MongoDatabaseFactory factory = MongoDatabaseFactory.create(mongo, "foo");
MongoDatabaseFactory wrapped = factory.withSession(clientSession).withSession(clientSession);
InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase());

43
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/observability/TestConfig.java

@ -15,6 +15,13 @@ @@ -15,6 +15,13 @@
*/
package org.springframework.data.mongodb.observability;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.test.simple.SimpleTracer;
import java.util.Properties;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
@ -27,8 +34,6 @@ import org.springframework.data.mongodb.core.MongoOperations; @@ -27,8 +34,6 @@ import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
@ -43,15 +48,9 @@ import org.springframework.data.repository.core.support.PropertiesBasedNamedQuer @@ -43,15 +48,9 @@ import org.springframework.data.repository.core.support.PropertiesBasedNamedQuer
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.micrometer.observation.ObservationRegistry;
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.test.simple.SimpleTracer;
/**
* @author Mark Paluch
*/
@ -66,13 +65,23 @@ class TestConfig { @@ -66,13 +65,23 @@ class TestConfig {
}
@Bean
MongoDatabaseFactory mongoDatabaseFactory(MongoClientSettings settings) {
return new SimpleMongoClientDatabaseFactory(MongoClients.create(settings), "observable");
MongoClient mongoClient(MongoClientSettings settings) {
return MongoClients.create(settings);
}
@Bean
MongoDatabaseFactory mongoDatabaseFactory(MongoClient client) {
return MongoDatabaseFactory.create(client, "observable");
}
@Bean
ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(MongoClientSettings settings) {
return new SimpleReactiveMongoDatabaseFactory(com.mongodb.reactivestreams.client.MongoClients.create(settings),
com.mongodb.reactivestreams.client.MongoClient reactiveMongoClient(MongoClientSettings settings) {
return com.mongodb.reactivestreams.client.MongoClients.create(settings);
}
@Bean
ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(com.mongodb.reactivestreams.client.MongoClient client) {
return ReactiveMongoDatabaseFactory.create(client,
"observable");
}
@ -103,17 +112,13 @@ class TestConfig { @@ -103,17 +112,13 @@ class TestConfig {
@Bean
MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory, MongoConverter mongoConverter) {
MongoTemplate template = new MongoTemplate(mongoDatabaseFactory, mongoConverter);
return template;
return new MongoTemplate(mongoDatabaseFactory, mongoConverter);
}
@Bean
ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory,
MongoConverter mongoConverter) {
ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoDatabaseFactory, mongoConverter);
return template;
return new ReactiveMongoTemplate(mongoDatabaseFactory, mongoConverter);
}
@Bean

Loading…
Cancel
Save