Extend GridFsTemplate and its reactive variant to accept a provided GridFSBucket instance.

Allow to pass in a GridFSBucket from outside to avoid recreating instances on every method call.

Closes #1627
Original pull request:# 4389
This commit is contained in:
Christoph Strobl
2023-05-17 15:16:46 +02:00
committed by Mark Paluch
parent 5163e544ae
commit 4b78ef6523
3 changed files with 67 additions and 24 deletions

View File

@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import org.bson.Document;
import org.bson.types.ObjectId;
@@ -30,6 +31,7 @@ import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -56,9 +58,7 @@ import com.mongodb.client.gridfs.model.GridFSUploadOptions;
*/
public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOperations, ResourcePatternResolver {
private final MongoDatabaseFactory dbFactory;
private final @Nullable String bucket;
private Supplier<GridFSBucket> bucketSupplier;
/**
* Creates a new {@link GridFsTemplate} using the given {@link MongoDatabaseFactory} and {@link MongoConverter}.
@@ -78,13 +78,22 @@ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOpe
* @param bucket can be {@literal null}.
*/
public GridFsTemplate(MongoDatabaseFactory dbFactory, MongoConverter converter, @Nullable String bucket) {
this(converter, Lazy.of(() -> getGridFs(dbFactory, bucket)));
}
/**
* Creates a new {@link GridFsTemplate} using the given {@link MongoConverter} and {@link Supplier} providing the
* required {@link GridFSBucket}.
*
* @param converter must not be {@literal null}.
* @param gridFSBucket must not be {@literal null}.
* @since 4.2
*/
public GridFsTemplate(MongoConverter converter, Supplier<GridFSBucket> gridFSBucket) {
super(converter);
Assert.notNull(dbFactory, "MongoDbFactory must not be null");
this.dbFactory = dbFactory;
this.bucket = bucket;
this.bucketSupplier = gridFSBucket;
}
public ObjectId store(InputStream content, @Nullable String filename, @Nullable String contentType,
@@ -142,7 +151,7 @@ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOpe
}
public ClassLoader getClassLoader() {
return dbFactory.getClass().getClassLoader();
return this.getClassLoader();
}
public GridFsResource getResource(String location) {
@@ -182,7 +191,11 @@ public class GridFsTemplate extends GridFsOperationsSupport implements GridFsOpe
return new GridFsResource[] { getResource(locationPattern) };
}
private GridFSBucket getGridFs() {
GridFSBucket getGridFs() {
return this.bucketSupplier.get();
}
private static GridFSBucket getGridFs(MongoDatabaseFactory dbFactory, @Nullable String bucket) {
MongoDatabase db = dbFactory.getMongoDatabase();
return bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket);

View File

@@ -27,7 +27,6 @@ import org.bson.BsonValue;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
@@ -37,6 +36,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.SerializationUtils;
import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -61,9 +61,8 @@ import com.mongodb.reactivestreams.client.gridfs.GridFSUploadPublisher;
*/
public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements ReactiveGridFsOperations {
private final ReactiveMongoDatabaseFactory dbFactory;
private final DataBufferFactory dataBufferFactory;
private final @Nullable String bucket;
private Mono<GridFSBucket> bucketSupplier;
/**
* Creates a new {@link ReactiveGridFsTemplate} using the given {@link ReactiveMongoDatabaseFactory} and
@@ -100,15 +99,27 @@ public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements R
*/
public ReactiveGridFsTemplate(DataBufferFactory dataBufferFactory, ReactiveMongoDatabaseFactory dbFactory,
MongoConverter converter, @Nullable String bucket) {
this(converter, Mono.defer(Lazy.of(() -> doGetBucket(dbFactory, bucket))), dataBufferFactory);
}
/**
* Creates a new {@link ReactiveGridFsTemplate} using the given {@link MongoConverter}, {@link Mono} emitting a
* {@link ReactiveMongoDatabaseFactory} and {@link DataBufferFactory}.
*
* @param converter must not be {@literal null}.
* @param gridFSBucket must not be {@literal null}.
* @param dataBufferFactory must not be {@literal null}.
* @since 4.2
*/
public ReactiveGridFsTemplate(MongoConverter converter, Mono<GridFSBucket> gridFSBucket,
DataBufferFactory dataBufferFactory) {
super(converter);
Assert.notNull(dataBufferFactory, "DataBufferFactory must not be null");
Assert.notNull(dbFactory, "ReactiveMongoDatabaseFactory must not be null");
this.bucketSupplier = gridFSBucket;
this.dataBufferFactory = dataBufferFactory;
this.dbFactory = dbFactory;
this.bucket = bucket;
}
@Override
@@ -247,11 +258,15 @@ public class ReactiveGridFsTemplate extends GridFsOperationsSupport implements R
return doGetBucket().flatMapMany(callback::doInBucket);
}
protected Mono<GridFSBucket> doGetBucket() {
static Mono<GridFSBucket> doGetBucket(ReactiveMongoDatabaseFactory dbFactory, @Nullable String bucket) {
return dbFactory.getMongoDatabase()
.map(db -> bucket == null ? GridFSBuckets.create(db) : GridFSBuckets.create(db, bucket));
}
protected Mono<GridFSBucket> doGetBucket() {
return bucketSupplier;
}
/**
* @param <T>
* @author Mathieu Ouellet

View File

@@ -20,6 +20,11 @@ import static org.springframework.test.util.ReflectionTestUtils.*;
import javax.net.ssl.SSLSocketFactory;
import java.util.function.Supplier;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.model.GridFSFile;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -168,8 +173,12 @@ public class MongoNamespaceTests {
assertThat(ctx.containsBean("gridFsTemplate")).isTrue();
GridFsOperations operations = (GridFsOperations) ctx.getBean("gridFsTemplate");
MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory");
assertThat(getField(dbf, "databaseName")).isEqualTo("database");
Supplier<GridFSBucket> gridFSBucketSupplier = (Supplier<GridFSBucket>) getField(operations, "bucketSupplier");
GridFSBucket gfsBucket = gridFSBucketSupplier.get();
assertThat(gfsBucket.getBucketName()).isEqualTo("fs"); // fs is the default
MongoCollection<GridFSFile> filesCollection = (MongoCollection<GridFSFile>) getField(gfsBucket, "filesCollection");
assertThat(filesCollection.getNamespace().getDatabaseName()).isEqualTo("database");
MongoConverter converter = (MongoConverter) getField(operations, "converter");
assertThat(converter).isNotNull();
@@ -181,9 +190,12 @@ public class MongoNamespaceTests {
assertThat(ctx.containsBean("secondGridFsTemplate")).isTrue();
GridFsOperations operations = (GridFsOperations) ctx.getBean("secondGridFsTemplate");
MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory");
assertThat(getField(dbf, "databaseName")).isEqualTo("database");
assertThat(getField(operations, "bucket")).isEqualTo(null);
Supplier<GridFSBucket> gridFSBucketSupplier = (Supplier<GridFSBucket>) getField(operations, "bucketSupplier");
GridFSBucket gfsBucket = gridFSBucketSupplier.get();
assertThat(gfsBucket.getBucketName()).isEqualTo("fs"); // fs is the default
MongoCollection<GridFSFile> filesCollection = (MongoCollection<GridFSFile>) getField(gfsBucket, "filesCollection");
assertThat(filesCollection.getNamespace().getDatabaseName()).isEqualTo("database");
MongoConverter converter = (MongoConverter) getField(operations, "converter");
assertThat(converter).isNotNull();
@@ -195,9 +207,12 @@ public class MongoNamespaceTests {
assertThat(ctx.containsBean("thirdGridFsTemplate")).isTrue();
GridFsOperations operations = (GridFsOperations) ctx.getBean("thirdGridFsTemplate");
MongoDatabaseFactory dbf = (MongoDatabaseFactory) getField(operations, "dbFactory");
assertThat(getField(dbf, "databaseName")).isEqualTo("database");
assertThat(getField(operations, "bucket")).isEqualTo("bucketString");
Supplier<GridFSBucket> gridFSBucketSupplier = (Supplier<GridFSBucket>) getField(operations, "bucketSupplier");
GridFSBucket gfsBucket = gridFSBucketSupplier.get();
assertThat(gfsBucket.getBucketName()).isEqualTo("bucketString"); // fs is the default
MongoCollection<GridFSFile> filesCollection = (MongoCollection<GridFSFile>) getField(gfsBucket, "filesCollection");
assertThat(filesCollection.getNamespace().getDatabaseName()).isEqualTo("database");
MongoConverter converter = (MongoConverter) getField(operations, "converter");
assertThat(converter).isNotNull();