Skip to content

Commit 4e11a2c

Browse files
committed
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
1 parent 214e4f4 commit 4e11a2c

File tree

7 files changed

+131
-27
lines changed

7 files changed

+131
-27
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616
package org.springframework.data.mongodb;
1717

1818
import org.bson.codecs.configuration.CodecRegistry;
19+
1920
import org.springframework.dao.DataAccessException;
2021
import org.springframework.dao.support.PersistenceExceptionTranslator;
2122
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
23+
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
24+
import org.springframework.util.Assert;
2225

2326
import com.mongodb.ClientSessionOptions;
27+
import com.mongodb.ConnectionString;
2428
import com.mongodb.client.ClientSession;
29+
import com.mongodb.client.MongoClient;
2530
import com.mongodb.client.MongoDatabase;
2631

2732
/**
@@ -30,10 +35,56 @@
3035
* @author Mark Pollack
3136
* @author Thomas Darimont
3237
* @author Christoph Strobl
38+
* @author Mark Paluch
3339
* @since 3.0
3440
*/
3541
public interface MongoDatabaseFactory extends CodecRegistryProvider, MongoSessionProvider {
3642

43+
/**
44+
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance for the given {@code connectionString}. Using this
45+
* factory method will create a new {@link MongoClient} instance that will be closed when calling
46+
* {@link SimpleMongoClientDatabaseFactory#destroy()}.
47+
*
48+
* @param connectionString connection coordinates for a database connection. Must contain a database name and must not
49+
* be {@literal null} or empty.
50+
* @since 4.5.2
51+
* @see <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Connection String reference</a>
52+
*/
53+
static SimpleMongoClientDatabaseFactory create(String connectionString) {
54+
55+
Assert.notNull(connectionString, "ConnectionString must not be null");
56+
57+
return new SimpleMongoClientDatabaseFactory(connectionString);
58+
}
59+
60+
/**
61+
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. Using this
62+
* factory will create a new {@link MongoClient} instance that will be closed when calling
63+
* {@link SimpleMongoClientDatabaseFactory#destroy()}.
64+
*
65+
* @param connectionString connection coordinates for a database connection. Must contain also a database name and not
66+
* be {@literal null}.
67+
* @since 4.5.2
68+
*/
69+
static SimpleMongoClientDatabaseFactory create(ConnectionString connectionString) {
70+
71+
Assert.notNull(connectionString, "ConnectionString must not be null");
72+
73+
return new SimpleMongoClientDatabaseFactory(connectionString);
74+
}
75+
76+
/**
77+
* Creates a new {@link MongoDatabaseFactory} instance from the given {@link MongoClient}. We assume a managed client
78+
* instance that will be disposed by you (or the application container) once the client is no longer required for use.
79+
*
80+
* @param mongoClient must not be {@literal null}.
81+
* @param databaseName must not be {@literal null} or empty.
82+
* @since 4.5.2
83+
*/
84+
static MongoDatabaseFactory create(MongoClient mongoClient, String databaseName) {
85+
return new SimpleMongoClientDatabaseFactory(mongoClient, databaseName);
86+
}
87+
3788
/**
3889
* Obtain a {@link MongoDatabase} from the underlying factory.
3990
*

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
public interface MongoSessionProvider {
3232

3333
/**
34-
* Obtain a {@link ClientSession} with with given options.
34+
* Obtain a {@link ClientSession} with given options.
3535
*
3636
* @param options must not be {@literal null}.
3737
* @return never {@literal null}.

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@
1818
import reactor.core.publisher.Mono;
1919

2020
import org.bson.codecs.configuration.CodecRegistry;
21+
2122
import org.springframework.dao.DataAccessException;
2223
import org.springframework.dao.support.PersistenceExceptionTranslator;
2324
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
25+
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
26+
import org.springframework.util.Assert;
2427

2528
import com.mongodb.ClientSessionOptions;
29+
import com.mongodb.ConnectionString;
2630
import com.mongodb.reactivestreams.client.ClientSession;
31+
import com.mongodb.reactivestreams.client.MongoClient;
2732
import com.mongodb.reactivestreams.client.MongoDatabase;
2833

2934
/**
@@ -36,6 +41,51 @@
3641
*/
3742
public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
3843

44+
/**
45+
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance for the given {@code connectionString}. Using
46+
* this factory method will create a new {@link MongoClient} instance that will be closed when calling
47+
* {@link SimpleReactiveMongoDatabaseFactory#destroy()}.
48+
*
49+
* @param connectionString connection coordinates for a database connection. Must contain a database name and must not
50+
* be {@literal null} or empty.
51+
* @since 4.5.2
52+
* @see <a href="https://docs.mongodb.com/manual/reference/connection-string/">MongoDB Connection String reference</a>
53+
*/
54+
static SimpleReactiveMongoDatabaseFactory create(String connectionString) {
55+
56+
Assert.notNull(connectionString, "ConnectionString must not be null");
57+
58+
return create(new ConnectionString(connectionString));
59+
}
60+
61+
/**
62+
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link MongoClient}. Using this
63+
* factory will create a new {@link MongoClient} instance that will be closed when calling
64+
* {@link SimpleReactiveMongoDatabaseFactory#destroy()}.
65+
*
66+
* @param connectionString connection coordinates for a database connection. Must contain also a database name and not
67+
* be {@literal null}.
68+
* @since 4.5.2
69+
*/
70+
static SimpleReactiveMongoDatabaseFactory create(ConnectionString connectionString) {
71+
72+
Assert.notNull(connectionString, "ConnectionString must not be null");
73+
74+
return new SimpleReactiveMongoDatabaseFactory(connectionString);
75+
}
76+
77+
/**
78+
* Creates a new {@link MongoDatabaseFactory} instance from the given {@link MongoClient}. We assume a managed client
79+
* instance that will be disposed by you (or the application container) once the client is no longer required for use.
80+
*
81+
* @param mongoClient must not be {@literal null}.
82+
* @param databaseName must not be {@literal null} or empty.
83+
* @since 4.5.2
84+
*/
85+
static ReactiveMongoDatabaseFactory create(MongoClient mongoClient, String databaseName) {
86+
return new SimpleReactiveMongoDatabaseFactory(mongoClient, databaseName);
87+
}
88+
3989
/**
4090
* Creates a default {@link MongoDatabase} instance.
4191
*

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.springframework.data.mongodb.MongoDatabaseFactory;
2121
import org.springframework.data.mongodb.SpringDataMongoDB;
2222
import org.springframework.data.mongodb.core.MongoTemplate;
23-
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
2423
import org.springframework.data.mongodb.core.convert.DbRefResolver;
2524
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
2625
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
@@ -75,7 +74,7 @@ public MongoTemplate mongoTemplate(MongoDatabaseFactory databaseFactory, Mapping
7574
*/
7675
@Bean
7776
public MongoDatabaseFactory mongoDbFactory() {
78-
return new SimpleMongoClientDatabaseFactory(mongoClient(), getDatabaseName());
77+
return MongoDatabaseFactory.create(mongoClient(), getDatabaseName());
7978
}
8079

8180
/**

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.springframework.data.mongodb.SpringDataMongoDB;
2222
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
2323
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
24-
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
2524
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
2625
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
2726
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
@@ -79,7 +78,7 @@ public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory
7978
*/
8079
@Bean
8180
public ReactiveMongoDatabaseFactory reactiveMongoDbFactory() {
82-
return new SimpleReactiveMongoDatabaseFactory(reactiveMongoClient(), getDatabaseName());
81+
return ReactiveMongoDatabaseFactory.create(reactiveMongoClient(), getDatabaseName());
8382
}
8483

8584
/**

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void mongoUriConstructor() {
7272

7373
ConnectionString mongoURI = new ConnectionString(
7474
"mongodb://myUsername:myPassword@localhost/myDatabase.myCollection");
75-
MongoDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(mongoURI);
75+
SimpleMongoClientDatabaseFactory mongoDbFactory = MongoDatabaseFactory.create(mongoURI);
7676

7777
assertThat(mongoDbFactory).hasFieldOrPropertyWithValue("databaseName", "myDatabase");
7878
}
@@ -82,7 +82,7 @@ void constructsMongoClientAccordingToMongoUri() {
8282

8383
ConnectionString uri = new ConnectionString(
8484
"mongodb://myUserName:[email protected]:27017/myDataBase.myCollection");
85-
SimpleMongoClientDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(uri);
85+
SimpleMongoClientDatabaseFactory factory = MongoDatabaseFactory.create(uri);
8686

8787
assertThat(factory).hasFieldOrPropertyWithValue("databaseName", "myDataBase");
8888
}
@@ -92,7 +92,7 @@ void cascadedWithSessionUsesRootFactory() {
9292

9393
when(mongo.getDatabase("foo")).thenReturn(database);
9494

95-
MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(mongo, "foo");
95+
MongoDatabaseFactory factory = MongoDatabaseFactory.create(mongo, "foo");
9696
MongoDatabaseFactory wrapped = factory.withSession(clientSession).withSession(clientSession);
9797

9898
InvocationHandler invocationHandler = Proxy.getInvocationHandler(wrapped.getMongoDatabase());

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
*/
1616
package org.springframework.data.mongodb.observability;
1717

18+
import io.micrometer.core.instrument.MeterRegistry;
19+
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
20+
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
21+
import io.micrometer.observation.ObservationRegistry;
22+
import io.micrometer.tracing.Tracer;
23+
import io.micrometer.tracing.test.simple.SimpleTracer;
24+
1825
import java.util.Properties;
1926

2027
import org.springframework.beans.factory.config.PropertiesFactoryBean;
@@ -27,8 +34,6 @@
2734
import org.springframework.data.mongodb.core.MongoTemplate;
2835
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
2936
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
30-
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
31-
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
3237
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
3338
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
3439
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -43,15 +48,9 @@
4348

4449
import com.mongodb.ConnectionString;
4550
import com.mongodb.MongoClientSettings;
51+
import com.mongodb.client.MongoClient;
4652
import com.mongodb.client.MongoClients;
4753

48-
import io.micrometer.core.instrument.MeterRegistry;
49-
import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler;
50-
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
51-
import io.micrometer.observation.ObservationRegistry;
52-
import io.micrometer.tracing.Tracer;
53-
import io.micrometer.tracing.test.simple.SimpleTracer;
54-
5554
/**
5655
* @author Mark Paluch
5756
*/
@@ -66,13 +65,23 @@ class TestConfig {
6665
}
6766

6867
@Bean
69-
MongoDatabaseFactory mongoDatabaseFactory(MongoClientSettings settings) {
70-
return new SimpleMongoClientDatabaseFactory(MongoClients.create(settings), "observable");
68+
MongoClient mongoClient(MongoClientSettings settings) {
69+
return MongoClients.create(settings);
70+
}
71+
72+
@Bean
73+
MongoDatabaseFactory mongoDatabaseFactory(MongoClient client) {
74+
return MongoDatabaseFactory.create(client, "observable");
7175
}
7276

7377
@Bean
74-
ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(MongoClientSettings settings) {
75-
return new SimpleReactiveMongoDatabaseFactory(com.mongodb.reactivestreams.client.MongoClients.create(settings),
78+
com.mongodb.reactivestreams.client.MongoClient reactiveMongoClient(MongoClientSettings settings) {
79+
return com.mongodb.reactivestreams.client.MongoClients.create(settings);
80+
}
81+
82+
@Bean
83+
ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory(com.mongodb.reactivestreams.client.MongoClient client) {
84+
return ReactiveMongoDatabaseFactory.create(client,
7685
"observable");
7786
}
7887

@@ -103,17 +112,13 @@ MongoMappingContext mappingContext() {
103112

104113
@Bean
105114
MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory, MongoConverter mongoConverter) {
106-
107-
MongoTemplate template = new MongoTemplate(mongoDatabaseFactory, mongoConverter);
108-
return template;
115+
return new MongoTemplate(mongoDatabaseFactory, mongoConverter);
109116
}
110117

111118
@Bean
112119
ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory,
113120
MongoConverter mongoConverter) {
114-
115-
ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoDatabaseFactory, mongoConverter);
116-
return template;
121+
return new ReactiveMongoTemplate(mongoDatabaseFactory, mongoConverter);
117122
}
118123

119124
@Bean

0 commit comments

Comments
 (0)