Skip to content

Commit 0bb302c

Browse files
committed
Document client disposal using MongoDatabaseFactory.
Closes #5012
1 parent ebb7b58 commit 0bb302c

File tree

3 files changed

+30
-99
lines changed

3 files changed

+30
-99
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoDatabaseFactorySupport.java

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
package org.springframework.data.mongodb.core;
1717

1818
import org.jspecify.annotations.Nullable;
19+
1920
import org.springframework.aop.framework.ProxyFactory;
2021
import org.springframework.dao.DataAccessException;
2122
import org.springframework.dao.support.PersistenceExceptionTranslator;
2223
import org.springframework.data.mongodb.MongoDatabaseFactory;
2324
import org.springframework.data.mongodb.SessionAwareMethodInterceptor;
2425
import org.springframework.lang.Contract;
2526
import org.springframework.util.Assert;
26-
import org.springframework.util.ObjectUtils;
2727

2828
import com.mongodb.ClientSessionOptions;
2929
import com.mongodb.WriteConcern;
@@ -33,8 +33,7 @@
3333

3434
/**
3535
* Common base class for usage with both {@link com.mongodb.client.MongoClients} defining common properties such as
36-
* database name and exception translator. <br />
37-
* Not intended to be used directly.
36+
* database name and exception translator. Not intended to be used directly.
3837
*
3938
* @author Christoph Strobl
4039
* @author Mark Paluch
@@ -126,6 +125,7 @@ public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException
126125
*/
127126
protected abstract MongoDatabase doGetMongoDatabase(String dbName);
128127

128+
129129
public void destroy() throws Exception {
130130
if (mongoInstanceCreated) {
131131
closeClient();
@@ -164,15 +164,8 @@ protected String getDefaultDatabaseName() {
164164
* @author Christoph Strobl
165165
* @since 2.1
166166
*/
167-
static final class ClientSessionBoundMongoDbFactory implements MongoDatabaseFactory {
168-
169-
private final ClientSession session;
170-
private final MongoDatabaseFactory delegate;
171-
172-
public ClientSessionBoundMongoDbFactory(ClientSession session, MongoDatabaseFactory delegate) {
173-
this.session = session;
174-
this.delegate = delegate;
175-
}
167+
record ClientSessionBoundMongoDbFactory(ClientSession session,
168+
MongoDatabaseFactory delegate) implements MongoDatabaseFactory {
176169

177170
@Override
178171
public MongoDatabase getMongoDatabase() throws DataAccessException {
@@ -201,7 +194,7 @@ public MongoDatabaseFactory withSession(ClientSession session) {
201194

202195
@Override
203196
public boolean isTransactionActive() {
204-
return session != null && session.hasActiveTransaction();
197+
return session.hasActiveTransaction();
205198
}
206199

207200
private MongoDatabase proxyMongoDatabase(MongoDatabase database) {
@@ -230,39 +223,6 @@ private <T> T createProxyInstance(com.mongodb.session.ClientSession session, T t
230223
return targetType.cast(factory.getProxy(target.getClass().getClassLoader()));
231224
}
232225

233-
public ClientSession getSession() {
234-
return this.session;
235-
}
236-
237-
public MongoDatabaseFactory getDelegate() {
238-
return this.delegate;
239-
}
240-
241-
@Override
242-
public boolean equals(@Nullable Object o) {
243-
if (this == o)
244-
return true;
245-
if (o == null || getClass() != o.getClass())
246-
return false;
247-
248-
ClientSessionBoundMongoDbFactory that = (ClientSessionBoundMongoDbFactory) o;
249-
250-
if (!ObjectUtils.nullSafeEquals(this.session, that.session)) {
251-
return false;
252-
}
253-
return ObjectUtils.nullSafeEquals(this.delegate, that.delegate);
254-
}
255-
256-
@Override
257-
public int hashCode() {
258-
int result = ObjectUtils.nullSafeHashCode(this.session);
259-
result = 31 * result + ObjectUtils.nullSafeHashCode(this.delegate);
260-
return result;
261-
}
262-
263-
public String toString() {
264-
return "MongoDatabaseFactorySupport.ClientSessionBoundMongoDbFactory(session=" + this.getSession() + ", delegate="
265-
+ this.getDelegate() + ")";
266-
}
267226
}
227+
268228
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoClientDatabaseFactory.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public class SimpleMongoClientDatabaseFactory extends MongoDatabaseFactorySuppor
3434
implements DisposableBean {
3535

3636
/**
37-
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance for the given {@code connectionString}.
37+
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance for the given {@code connectionString}. Using this
38+
* constructor will create a new {@link MongoClient} instance that will be closed when calling {@link #destroy()}.
3839
*
3940
* @param connectionString connection coordinates for a database connection. Must contain a database name and must not
4041
* be {@literal null} or empty.
@@ -45,7 +46,8 @@ public SimpleMongoClientDatabaseFactory(String connectionString) {
4546
}
4647

4748
/**
48-
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}.
49+
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. Using this
50+
* constructor will create a new {@link MongoClient} instance that will be closed when calling {@link #destroy()}.
4951
*
5052
* @param connectionString connection coordinates for a database connection. Must contain also a database name and not
5153
* be {@literal null}.
@@ -55,7 +57,10 @@ public SimpleMongoClientDatabaseFactory(ConnectionString connectionString) {
5557
}
5658

5759
/**
58-
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}.
60+
* Creates a new {@link SimpleMongoClientDatabaseFactory} instance from the given {@link MongoClient}. Note that the
61+
* client will not be closed when calling {@link #destroy()} as we assume a managed client instance that we do not
62+
* want to close on {@link #destroy()} meaning that you (or the application container) must dispose the client
63+
* instance once it is no longer required for use.
5964
*
6065
* @param mongoClient must not be {@literal null}.
6166
* @param databaseName must not be {@literal null} or empty.
@@ -89,4 +94,5 @@ protected void closeClient() {
8994
protected MongoDatabase doGetMongoDatabase(String dbName) {
9095
return getMongoClient().getDatabase(dbName);
9196
}
97+
9298
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleReactiveMongoDatabaseFactory.java

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919

2020
import org.bson.codecs.configuration.CodecRegistry;
2121
import org.jspecify.annotations.Nullable;
22+
2223
import org.springframework.aop.framework.ProxyFactory;
2324
import org.springframework.beans.factory.DisposableBean;
2425
import org.springframework.dao.DataAccessException;
2526
import org.springframework.dao.support.PersistenceExceptionTranslator;
2627
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
2728
import org.springframework.data.mongodb.SessionAwareMethodInterceptor;
2829
import org.springframework.util.Assert;
29-
import org.springframework.util.ObjectUtils;
3030

3131
import com.mongodb.ClientSessionOptions;
3232
import com.mongodb.ConnectionString;
@@ -55,7 +55,9 @@ public class SimpleReactiveMongoDatabaseFactory implements DisposableBean, React
5555
private @Nullable WriteConcern writeConcern;
5656

5757
/**
58-
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link ConnectionString}.
58+
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link ConnectionString}. Using
59+
* this constructor will create a new {@link MongoClient} instance that will be closed when calling
60+
* {@link #destroy()}.
5961
*
6062
* @param connectionString must not be {@literal null}.
6163
*/
@@ -64,7 +66,10 @@ public SimpleReactiveMongoDatabaseFactory(ConnectionString connectionString) {
6466
}
6567

6668
/**
67-
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link MongoClient}.
69+
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link MongoClient}. Note that the
70+
* client will not be closed when calling {@link #destroy()} as we assume a managed client instance that we do not
71+
* want to close on {@link #destroy()} meaning that you (or the application container) must dispose the client
72+
* instance once it is no longer required for use.
6873
*
6974
* @param mongoClient must not be {@literal null}.
7075
* @param databaseName must not be {@literal null}.
@@ -163,16 +168,8 @@ public ReactiveMongoDatabaseFactory withSession(ClientSession session) {
163168
* @author Christoph Strobl
164169
* @since 2.1
165170
*/
166-
static final class ClientSessionBoundMongoDbFactory implements ReactiveMongoDatabaseFactory {
167-
168-
private final ClientSession session;
169-
private final ReactiveMongoDatabaseFactory delegate;
170-
171-
ClientSessionBoundMongoDbFactory(ClientSession session, ReactiveMongoDatabaseFactory delegate) {
172-
173-
this.session = session;
174-
this.delegate = delegate;
175-
}
171+
record ClientSessionBoundMongoDbFactory(ClientSession session,
172+
ReactiveMongoDatabaseFactory delegate) implements ReactiveMongoDatabaseFactory {
176173

177174
@Override
178175
public Mono<MongoDatabase> getMongoDatabase() throws DataAccessException {
@@ -206,7 +203,7 @@ public ReactiveMongoDatabaseFactory withSession(ClientSession session) {
206203

207204
@Override
208205
public boolean isTransactionActive() {
209-
return session != null && session.hasActiveTransaction();
206+
return session.hasActiveTransaction();
210207
}
211208

212209
private MongoDatabase decorateDatabase(MongoDatabase database) {
@@ -217,7 +214,8 @@ private MongoDatabase proxyDatabase(com.mongodb.session.ClientSession session, M
217214
return createProxyInstance(session, database, MongoDatabase.class);
218215
}
219216

220-
private MongoCollection proxyCollection(com.mongodb.session.ClientSession session, MongoCollection collection) {
217+
private MongoCollection<?> proxyCollection(com.mongodb.session.ClientSession session,
218+
MongoCollection<?> collection) {
221219
return createProxyInstance(session, collection, MongoCollection.class);
222220
}
223221

@@ -234,39 +232,6 @@ private <T> T createProxyInstance(com.mongodb.session.ClientSession session, T t
234232
return targetType.cast(factory.getProxy(target.getClass().getClassLoader()));
235233
}
236234

237-
public ClientSession getSession() {
238-
return this.session;
239-
}
240-
241-
public ReactiveMongoDatabaseFactory getDelegate() {
242-
return this.delegate;
243-
}
244-
245-
@Override
246-
public boolean equals(@Nullable Object o) {
247-
if (this == o)
248-
return true;
249-
if (o == null || getClass() != o.getClass())
250-
return false;
251-
252-
ClientSessionBoundMongoDbFactory that = (ClientSessionBoundMongoDbFactory) o;
253-
254-
if (!ObjectUtils.nullSafeEquals(this.session, that.session)) {
255-
return false;
256-
}
257-
return ObjectUtils.nullSafeEquals(this.delegate, that.delegate);
258-
}
259-
260-
@Override
261-
public int hashCode() {
262-
int result = ObjectUtils.nullSafeHashCode(this.session);
263-
result = 31 * result + ObjectUtils.nullSafeHashCode(this.delegate);
264-
return result;
265-
}
266-
267-
public String toString() {
268-
return "SimpleReactiveMongoDatabaseFactory.ClientSessionBoundMongoDbFactory(session=" + this.getSession()
269-
+ ", delegate=" + this.getDelegate() + ")";
270-
}
271235
}
236+
272237
}

0 commit comments

Comments
 (0)