Browse Source

DATAMONGO-2479 - Polishing.

Tweak Javadoc. Update reference documentation. Slightly refactor reactive flows to reduce operator count.

Simplify test fixtures and remove Google Guava usage. Reformat code.

Original pull request: #839.
pull/842/head
Mark Paluch 6 years ago
parent
commit
4f0dc04a81
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 47
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultBulkOperations.java
  2. 43
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  3. 116
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
  4. 10
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java
  5. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java
  6. 1
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java
  7. 1
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java
  8. 13
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java
  9. 6
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java
  10. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java
  11. 3
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java
  12. 378
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
  13. 300
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
  14. 12
      src/main/asciidoc/reference/mongo-entity-callbacks.adoc

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

@ -424,51 +424,52 @@ class DefaultBulkOperations implements BulkOperations {
models.add(new SourceAwareWriteModelHolder(source, model)); models.add(new SourceAwareWriteModelHolder(source, model));
} }
private void maybeEmitBeforeSaveEvent(SourceAwareWriteModelHolder it) { private void maybeEmitBeforeSaveEvent(SourceAwareWriteModelHolder holder) {
if (it.getModel() instanceof InsertOneModel) { if (holder.getModel() instanceof InsertOneModel) {
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument(); Document target = ((InsertOneModel<Document>) holder.getModel()).getDocument();
maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName)); maybeEmitEvent(new BeforeSaveEvent<>(holder.getSource(), target, collectionName));
} else if (it.getModel() instanceof ReplaceOneModel) { } else if (holder.getModel() instanceof ReplaceOneModel) {
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement(); Document target = ((ReplaceOneModel<Document>) holder.getModel()).getReplacement();
maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName)); maybeEmitEvent(new BeforeSaveEvent<>(holder.getSource(), target, collectionName));
} }
} }
private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder it) { private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder holder) {
if (it.getModel() instanceof InsertOneModel) { if (holder.getModel() instanceof InsertOneModel) {
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument(); Document target = ((InsertOneModel<Document>) holder.getModel()).getDocument();
maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName)); maybeEmitEvent(new AfterSaveEvent<>(holder.getSource(), target, collectionName));
} else if (it.getModel() instanceof ReplaceOneModel) { } else if (holder.getModel() instanceof ReplaceOneModel) {
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement(); Document target = ((ReplaceOneModel<Document>) holder.getModel()).getReplacement();
maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName)); maybeEmitEvent(new AfterSaveEvent<>(holder.getSource(), target, collectionName));
} }
} }
private void maybeInvokeAfterSaveCallback(SourceAwareWriteModelHolder it) { private void maybeInvokeAfterSaveCallback(SourceAwareWriteModelHolder holder) {
if (it.getModel() instanceof InsertOneModel) { if (holder.getModel() instanceof InsertOneModel) {
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument(); Document target = ((InsertOneModel<Document>) holder.getModel()).getDocument();
maybeInvokeAfterSaveCallback(it.getSource(), target); maybeInvokeAfterSaveCallback(holder.getSource(), target);
} else if (it.getModel() instanceof ReplaceOneModel) { } else if (holder.getModel() instanceof ReplaceOneModel) {
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement(); Document target = ((ReplaceOneModel<Document>) holder.getModel()).getReplacement();
maybeInvokeAfterSaveCallback(it.getSource(), target); maybeInvokeAfterSaveCallback(holder.getSource(), target);
} }
} }
private <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) { private <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) {
if (null != bulkOperationContext.getEventPublisher()) { if (bulkOperationContext.getEventPublisher() == null) {
bulkOperationContext.getEventPublisher().publishEvent(event); return event;
} }
bulkOperationContext.getEventPublisher().publishEvent(event);
return event; return event;
} }

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

@ -71,7 +71,16 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.*; import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.JsonSchemaMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper;
import org.springframework.data.mongodb.core.convert.MongoWriter;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.convert.UpdateMapper;
import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.index.IndexOperationsProvider; import org.springframework.data.mongodb.core.index.IndexOperationsProvider;
import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher;
@ -111,7 +120,16 @@ import com.mongodb.ClientSessionOptions;
import com.mongodb.MongoException; import com.mongodb.MongoException;
import com.mongodb.ReadPreference; import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern; import com.mongodb.WriteConcern;
import com.mongodb.client.*; import com.mongodb.client.AggregateIterable;
import com.mongodb.client.ClientSession;
import com.mongodb.client.DistinctIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.model.*; import com.mongodb.client.model.*;
import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult; import com.mongodb.client.result.UpdateResult;
@ -1047,6 +1065,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
T saved = doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, T saved = doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort,
queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, resultType); queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, resultType);
if (saved != null) { if (saved != null) {
maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName)); maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName));
return maybeCallAfterSave(saved, mappedReplacement, collectionName); return maybeCallAfterSave(saved, mappedReplacement, collectionName);
@ -1146,7 +1165,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
} }
protected void ensureNotIterable(@Nullable Object o) { protected void ensureNotIterable(@Nullable Object o) {
if (null != o) { if (o != null) {
if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) { if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) {
throw new IllegalArgumentException("Cannot use a collection here."); throw new IllegalArgumentException("Cannot use a collection here.");
} }
@ -2286,7 +2305,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) { protected <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) {
if (null != eventPublisher) { if (eventPublisher != null) {
eventPublisher.publishEvent(event); eventPublisher.publishEvent(event);
} }
@ -2295,7 +2314,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <T> T maybeCallBeforeConvert(T object, String collection) { protected <T> T maybeCallBeforeConvert(T object, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(BeforeConvertCallback.class, object, collection); return entityCallbacks.callback(BeforeConvertCallback.class, object, collection);
} }
@ -2304,7 +2323,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <T> T maybeCallBeforeSave(T object, Document document, String collection) { protected <T> T maybeCallBeforeSave(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(BeforeSaveCallback.class, object, document, collection); return entityCallbacks.callback(BeforeSaveCallback.class, object, document, collection);
} }
@ -2313,7 +2332,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <T> T maybeCallAfterSave(T object, Document document, String collection) { protected <T> T maybeCallAfterSave(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(AfterSaveCallback.class, object, document, collection); return entityCallbacks.callback(AfterSaveCallback.class, object, document, collection);
} }
@ -2322,7 +2341,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <T> T maybeCallAfterConvert(T object, Document document, String collection) { protected <T> T maybeCallAfterConvert(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(AfterConvertCallback.class, object, document, collection); return entityCallbacks.callback(AfterConvertCallback.class, object, document, collection);
} }
@ -3110,13 +3129,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Nullable @Nullable
public T doWith(@Nullable Document document) { public T doWith(@Nullable Document document) {
if (null != document) { if (document != null) {
maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName));
} }
T source = reader.read(type, document); T source = reader.read(type, document);
if (null != source) { if (source != null) {
maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName));
source = maybeCallAfterConvert(source, document, collectionName); source = maybeCallAfterConvert(source, document, collectionName);
} }
@ -3156,14 +3175,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Class<?> typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType Class<?> typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType
: targetType; : targetType;
if (null != document) { if (document != null) {
maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName)); maybeEmitEvent(new AfterLoadEvent<>(document, targetType, collectionName));
} }
Object source = reader.read(typeToRead, document); Object source = reader.read(typeToRead, document);
Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source;
if (null != result) { if (result != null) {
maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName)); maybeEmitEvent(new AfterConvertEvent<>(document, result, collectionName));
result = maybeCallAfterConvert(result, document, collectionName); result = maybeCallAfterConvert(result, document, collectionName);
} }

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

@ -39,6 +39,7 @@ import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber; import org.reactivestreams.Subscriber;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
@ -74,7 +75,16 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.*; import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.JsonSchemaMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.convert.MongoJsonSchemaMapper;
import org.springframework.data.mongodb.core.convert.MongoWriter;
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.convert.UpdateMapper;
import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher; import org.springframework.data.mongodb.core.index.MongoMappingEventPublisher;
import org.springframework.data.mongodb.core.index.ReactiveIndexOperations; import org.springframework.data.mongodb.core.index.ReactiveIndexOperations;
import org.springframework.data.mongodb.core.index.ReactiveMongoPersistentEntityIndexCreator; import org.springframework.data.mongodb.core.index.ReactiveMongoPersistentEntityIndexCreator;
@ -109,7 +119,16 @@ import com.mongodb.CursorType;
import com.mongodb.MongoException; import com.mongodb.MongoException;
import com.mongodb.ReadPreference; import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern; import com.mongodb.WriteConcern;
import com.mongodb.client.model.*; import com.mongodb.client.model.CountOptions;
import com.mongodb.client.model.CreateCollectionOptions;
import com.mongodb.client.model.DeleteOptions;
import com.mongodb.client.model.FindOneAndDeleteOptions;
import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReplaceOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.ValidationOptions;
import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.FullDocument;
import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.InsertOneResult;
@ -1145,27 +1164,28 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Document mappedFields = queryContext.getMappedFields(entity); Document mappedFields = queryContext.getMappedFields(entity);
Document mappedSort = queryContext.getMappedSort(entity); Document mappedSort = queryContext.getMappedSort(entity);
return Mono.just(PersistableEntityModel.of(replacement, collectionName)) // return Mono.defer(() -> {
.doOnNext(it -> maybeEmitEvent(new BeforeConvertEvent<>(it.getSource(), it.getCollection()))) //
.flatMap(it -> maybeCallBeforeConvert(it.getSource(), it.getCollection()).map(it::mutate))
.map(it -> it
.addTargetDocument(operations.forEntity(it.getSource()).toMappedDocument(mongoConverter).getDocument())) //
.doOnNext(it -> maybeEmitEvent(new BeforeSaveEvent(it.getSource(), it.getTarget(), it.getCollection()))) //
.flatMap(it -> {
PersistableEntityModel<S> flowObject = (PersistableEntityModel<S>) it; PersistableEntityModel<S> pem = PersistableEntityModel.of(replacement, collectionName);
return maybeCallBeforeSave(flowObject.getSource(), flowObject.getTarget(), flowObject.getCollection())
.map(potentiallyModified -> PersistableEntityModel.of(potentiallyModified, flowObject.getTarget(), maybeEmitEvent(new BeforeConvertEvent<>(pem.getSource(), pem.getCollection()));
flowObject.getCollection()));
return maybeCallBeforeConvert(pem.getSource(), pem.getCollection()).map(pem::mutate).flatMap(it -> {
PersistableEntityModel<S> mapped = it
.addTargetDocument(operations.forEntity(it.getSource()).toMappedDocument(mongoConverter).getDocument());
maybeEmitEvent(new BeforeSaveEvent(mapped.getSource(), mapped.getTarget(), mapped.getCollection()));
return maybeCallBeforeSave(it.getSource(), mapped.getTarget(), mapped.getCollection())
.map(potentiallyModified -> PersistableEntityModel.of(potentiallyModified, mapped.getTarget(),
mapped.getCollection()));
}).flatMap(it -> { }).flatMap(it -> {
PersistableEntityModel<S> flowObject = (PersistableEntityModel<S>) it; Mono<T> afterFindAndReplace = doFindAndReplace(it.getCollection(), mappedQuery, mappedFields, mappedSort,
Mono<T> afterFindAndReplace = doFindAndReplace(flowObject.getCollection(), mappedQuery, queryContext.getCollation(entityType).orElse(null), entityType, it.getTarget(), options, resultType);
mappedFields, mappedSort, queryContext.getCollation(entityType).orElse(null),
entityType, flowObject.getTarget(), options, resultType);
return afterFindAndReplace.flatMap(saved -> { return afterFindAndReplace.flatMap(saved -> {
maybeEmitEvent(new AfterSaveEvent<>(saved, flowObject.getTarget(), flowObject.getCollection())); maybeEmitEvent(new AfterSaveEvent<>(saved, it.getTarget(), it.getCollection()));
return maybeCallAfterSave(saved, flowObject.getTarget(), flowObject.getCollection()); return maybeCallAfterSave(saved, it.getTarget(), it.getCollection());
});
}); });
}); });
} }
@ -1314,13 +1334,14 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
AdaptibleEntity<T> entity = operations.forEntity(it.getSource(), mongoConverter.getConversionService()); AdaptibleEntity<T> entity = operations.forEntity(it.getSource(), mongoConverter.getConversionService());
entity.assertUpdateableIdIfNotSet(); entity.assertUpdateableIdIfNotSet();
return PersistableEntityModel.of(entity.initializeVersionProperty(), PersistableEntityModel<T> model = PersistableEntityModel.of(entity.initializeVersionProperty(),
entity.toMappedDocument(writer).getDocument(), it.getCollection()); entity.toMappedDocument(writer).getDocument(), it.getCollection());
}).doOnNext(it -> maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), it.getTarget(), it.getCollection()))) //
.flatMap(it -> {
maybeEmitEvent(new BeforeSaveEvent<>(model.getSource(), model.getTarget(), model.getCollection()));
return model;
})//
.flatMap(it -> {
return maybeCallBeforeSave(it.getSource(), it.getTarget(), it.getCollection()).map(it::mutate); return maybeCallBeforeSave(it.getSource(), it.getTarget(), it.getCollection()).map(it::mutate);
}).flatMap(it -> { }).flatMap(it -> {
return insertDocument(it.getCollection(), it.getTarget(), it.getSource().getClass()).flatMap(id -> { return insertDocument(it.getCollection(), it.getTarget(), it.getSource().getClass()).flatMap(id -> {
@ -2588,7 +2609,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) { protected <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) {
if (null != eventPublisher) { if (eventPublisher != null) {
eventPublisher.publishEvent(event); eventPublisher.publishEvent(event);
} }
@ -2597,7 +2618,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <T> Mono<T> maybeCallBeforeConvert(T object, String collection) { protected <T> Mono<T> maybeCallBeforeConvert(T object, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(ReactiveBeforeConvertCallback.class, object, collection); return entityCallbacks.callback(ReactiveBeforeConvertCallback.class, object, collection);
} }
@ -2606,7 +2627,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <T> Mono<T> maybeCallBeforeSave(T object, Document document, String collection) { protected <T> Mono<T> maybeCallBeforeSave(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(ReactiveBeforeSaveCallback.class, object, document, collection); return entityCallbacks.callback(ReactiveBeforeSaveCallback.class, object, document, collection);
} }
@ -2615,7 +2636,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <T> Mono<T> maybeCallAfterSave(T object, Document document, String collection) { protected <T> Mono<T> maybeCallAfterSave(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(ReactiveAfterSaveCallback.class, object, document, collection); return entityCallbacks.callback(ReactiveAfterSaveCallback.class, object, document, collection);
} }
@ -2624,7 +2645,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
protected <T> Mono<T> maybeCallAfterConvert(T object, Document document, String collection) { protected <T> Mono<T> maybeCallAfterConvert(T object, Document document, String collection) {
if (null != entityCallbacks) { if (entityCallbacks != null) {
return entityCallbacks.callback(ReactiveAfterConvertCallback.class, object, document, collection); return entityCallbacks.callback(ReactiveAfterConvertCallback.class, object, document, collection);
} }
@ -3092,23 +3113,18 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName)); maybeEmitEvent(new AfterLoadEvent<>(document, type, collectionName));
T source = reader.read(type, document); T source = reader.read(type, document);
if (null != source) { if (source != null) {
maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName)); maybeEmitEvent(new AfterConvertEvent<>(document, source, collectionName));
}
return Mono.defer(() -> {
if (null != source) {
return maybeCallAfterConvert(source, document, collectionName); return maybeCallAfterConvert(source, document, collectionName);
} else {
return Mono.empty();
} }
});
return Mono.empty();
} }
} }
/** /**
* {@link DocumentCallback} transforming {@link Document} into the given {@code targetType} or * {@link DocumentCallback} transforming {@link Document} into the given {@code targetType} or decorating the
* decorating the {@code sourceType} with a {@literal projection} in case the {@code targetType} is an * {@code sourceType} with a {@literal projection} in case the {@code targetType} is an {@literal interface}.
* {@literal interface}.
* *
* @param <S> * @param <S>
* @param <T> * @param <T>
@ -3137,18 +3153,13 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source; Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source;
T castEntity = (T) result; T castEntity = (T) result;
if (null != castEntity) { if (castEntity != null) {
maybeEmitEvent(new AfterConvertEvent<>(document, castEntity, collectionName)); maybeEmitEvent(new AfterConvertEvent<>(document, castEntity, collectionName));
return maybeCallAfterConvert(castEntity, document, collectionName);
} }
return Mono.defer(() -> {
if (null != castEntity) {
return maybeCallAfterConvert(castEntity, document, collectionName);
} else {
return Mono.empty(); return Mono.empty();
} }
});
}
} }
/** /**
@ -3184,15 +3195,18 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
public Mono<GeoResult<T>> doWith(Document object) { public Mono<GeoResult<T>> doWith(Document object) {
final double distance; double distance = getDistance(object);
return delegate.doWith(object).map(doWith -> new GeoResult<>(doWith, new Distance(distance, metric)));
}
double getDistance(Document object) {
if (object.containsKey(distanceField)) { if (object.containsKey(distanceField)) {
distance = NumberUtils.convertNumberToTargetClass(object.get(distanceField, Number.class), Double.class); return NumberUtils.convertNumberToTargetClass(object.get(distanceField, Number.class), Double.class);
} else {
distance = Double.NaN;
} }
return delegate.doWith(object) return Double.NaN;
.map(doWith -> new GeoResult<>(doWith, new Distance(distance, metric)));
} }
} }

10
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterConvertCallback.java

@ -19,22 +19,24 @@ import org.bson.Document;
import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallback;
/** /**
* Callback being invoked after a domain object is converted from a Document (when reading from the DB). * Callback being invoked after a domain object is materialized from a {@link Document} when reading results.
* *
* @author Roman Puchkovskiy * @author Roman Puchkovskiy
* @author Mark Paluch
* @since 3.0 * @since 3.0
* @see org.springframework.data.mapping.callback.EntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface AfterConvertCallback<T> extends EntityCallback<T> { public interface AfterConvertCallback<T> extends EntityCallback<T> {
/** /**
* Entity callback method invoked after a domain object is converted from a Document. Can return either the same * Entity callback method invoked after a domain object is materialized from a {@link Document}. Can return either the
* or a modified instance of the domain object. * same or a modified instance of the domain object.
* *
* @param entity the domain object (the result of the conversion). * @param entity the domain object (the result of the conversion).
* @param document must not be {@literal null}. * @param document must not be {@literal null}.
* @param collection name of the collection. * @param collection name of the collection.
* @return the domain object that is the result of the conversion from the Document. * @return the domain object that is the result of reading it from the {@link Document}.
*/ */
T onAfterConvert(T entity, Document document, String collection); T onAfterConvert(T entity, Document document, String collection);
} }

6
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterSaveCallback.java

@ -19,7 +19,7 @@ import org.bson.Document;
import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallback;
/** /**
* Entity callback triggered after save of a document. * Entity callback triggered after save of a {@link Document}.
* *
* @author Roman Puchkovskiy * @author Roman Puchkovskiy
* @since 3.0 * @since 3.0
@ -28,8 +28,8 @@ import org.springframework.data.mapping.callback.EntityCallback;
public interface AfterSaveCallback<T> extends EntityCallback<T> { public interface AfterSaveCallback<T> extends EntityCallback<T> {
/** /**
* Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance of
* of the domain object. * the domain object.
* *
* @param entity the domain object that was saved. * @param entity the domain object that was saved.
* @param document {@link Document} representing the {@code entity}. * @param document {@link Document} representing the {@code entity}.

1
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeConvertCallback.java

@ -22,6 +22,7 @@ import org.springframework.data.mapping.callback.EntityCallback;
* *
* @author Mark Paluch * @author Mark Paluch
* @since 2.2 * @since 2.2
* @see org.springframework.data.mapping.callback.EntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface BeforeConvertCallback<T> extends EntityCallback<T> { public interface BeforeConvertCallback<T> extends EntityCallback<T> {

1
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/BeforeSaveCallback.java

@ -24,6 +24,7 @@ import org.springframework.data.mapping.callback.EntityCallback;
* @author Mark Paluch * @author Mark Paluch
* @author Michael J. Simons * @author Michael J. Simons
* @since 2.2 * @since 2.2
* @see org.springframework.data.mapping.callback.EntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface BeforeSaveCallback<T> extends EntityCallback<T> { public interface BeforeSaveCallback<T> extends EntityCallback<T> {

13
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java

@ -17,27 +17,28 @@ package org.springframework.data.mongodb.core.mapping.event;
import org.bson.Document; import org.bson.Document;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
/** /**
* Callback being invoked after a domain object is converted from a Document (when reading from the DB). * Callback being invoked after a domain object is materialized from a {@link Document} when reading results.
* *
* @author Roman Puchkovskiy * @author Roman Puchkovskiy
* @author Mark Paluch
* @since 3.0 * @since 3.0
* @see ReactiveEntityCallbacks * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface ReactiveAfterConvertCallback<T> extends EntityCallback<T> { public interface ReactiveAfterConvertCallback<T> extends EntityCallback<T> {
/** /**
* Entity callback method invoked after a domain object is converted from a Document. Can return either the same * Entity callback method invoked after a domain object is materialized from a {@link Document}. Can return either the
* or a modified instance of the domain object. * same or a modified instance of the domain object.
* *
* @param entity the domain object (the result of the conversion). * @param entity the domain object (the result of the conversion).
* @param document must not be {@literal null}. * @param document must not be {@literal null}.
* @param collection name of the collection. * @param collection name of the collection.
* @return a {@link Publisher} emitting the domain object that is the result of the conversion from the Document. * @return a {@link Publisher} emitting the domain object that is the result of reading it from the {@link Document}.
*/ */
Publisher<T> onAfterConvert(T entity, Document document, String collection); Publisher<T> onAfterConvert(T entity, Document document, String collection);
} }

6
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterSaveCallback.java

@ -22,7 +22,7 @@ import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
/** /**
* Entity callback triggered after save of a document. * Entity callback triggered after save of a {@link Document}.
* *
* @author Roman Puchkovskiy * @author Roman Puchkovskiy
* @since 3.0 * @since 3.0
@ -32,8 +32,8 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
public interface ReactiveAfterSaveCallback<T> extends EntityCallback<T> { public interface ReactiveAfterSaveCallback<T> extends EntityCallback<T> {
/** /**
* Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance * Entity callback method invoked after a domain object is saved. Can return either the same or a modified instance of
* of the domain object. * the domain object.
* *
* @param entity the domain object that was saved. * @param entity the domain object that was saved.
* @param document {@link Document} representing the {@code entity}. * @param document {@link Document} representing the {@code entity}.

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeConvertCallback.java

@ -18,14 +18,13 @@ package org.springframework.data.mongodb.core.mapping.event;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
/** /**
* Callback being invoked before a domain object is converted to be persisted. * Callback being invoked before a domain object is converted to be persisted.
* *
* @author Mark Paluch * @author Mark Paluch
* @since 2.2 * @since 2.2
* @see ReactiveEntityCallbacks * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface ReactiveBeforeConvertCallback<T> extends EntityCallback<T> { public interface ReactiveBeforeConvertCallback<T> extends EntityCallback<T> {

3
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveBeforeSaveCallback.java

@ -19,14 +19,13 @@ import org.bson.Document;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
/** /**
* Entity callback triggered before save of a document. * Entity callback triggered before save of a document.
* *
* @author Mark Paluch * @author Mark Paluch
* @since 2.2 * @since 2.2
* @see ReactiveEntityCallbacks * @see org.springframework.data.mapping.callback.ReactiveEntityCallbacks
*/ */
@FunctionalInterface @FunctionalInterface
public interface ReactiveBeforeSaveCallback<T> extends EntityCallback<T> { public interface ReactiveBeforeSaveCallback<T> extends EntityCallback<T> {

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

File diff suppressed because it is too large Load Diff

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

@ -20,7 +20,9 @@ import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.test.util.Assertions.assertThat; import static org.springframework.data.mongodb.test.util.Assertions.assertThat;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.test.StepVerifier; import reactor.test.StepVerifier;
@ -86,7 +88,6 @@ import org.springframework.lang.Nullable;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import com.google.common.collect.ImmutableMap;
import com.mongodb.MongoClientSettings; import com.mongodb.MongoClientSettings;
import com.mongodb.ReadPreference; import com.mongodb.ReadPreference;
import com.mongodb.client.model.CountOptions; import com.mongodb.client.model.CountOptions;
@ -120,7 +121,7 @@ import com.mongodb.reactivestreams.client.MongoDatabase;
@MockitoSettings(strictness = Strictness.LENIENT) @MockitoSettings(strictness = Strictness.LENIENT)
public class ReactiveMongoTemplateUnitTests { public class ReactiveMongoTemplateUnitTests {
ReactiveMongoTemplate template; private ReactiveMongoTemplate template;
@Mock SimpleReactiveMongoDatabaseFactory factory; @Mock SimpleReactiveMongoDatabaseFactory factory;
@Mock MongoClient mongoClient; @Mock MongoClient mongoClient;
@ -136,12 +137,12 @@ public class ReactiveMongoTemplateUnitTests {
@Mock Publisher deletePublisher; @Mock Publisher deletePublisher;
@Mock MapReducePublisher mapReducePublisher; @Mock MapReducePublisher mapReducePublisher;
MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
MappingMongoConverter converter; private MappingMongoConverter converter;
MongoMappingContext mappingContext; private MongoMappingContext mappingContext;
@BeforeEach @BeforeEach
public void beforeEach() { void beforeEach() {
when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator);
when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry()); when(factory.getCodecRegistry()).thenReturn(MongoClientSettings.getDefaultCodecRegistry());
@ -187,23 +188,23 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1444 @Test // DATAMONGO-1444
public void rejectsNullDatabaseName() { void rejectsNullDatabaseName() {
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(mongoClient, null)); assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(mongoClient, null));
} }
@Test // DATAMONGO-1444 @Test // DATAMONGO-1444
public void rejectsNullMongo() { void rejectsNullMongo() {
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(null, "database")); assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMongoTemplate(null, "database"));
} }
@Test // DATAMONGO-1444 @Test // DATAMONGO-1444
public void defaultsConverterToMappingMongoConverter() throws Exception { void defaultsConverterToMappingMongoConverter() throws Exception {
ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoClient, "database"); ReactiveMongoTemplate template = new ReactiveMongoTemplate(mongoClient, "database");
assertThat(ReflectionTestUtils.getField(template, "mongoConverter") instanceof MappingMongoConverter).isTrue(); assertThat(ReflectionTestUtils.getField(template, "mongoConverter") instanceof MappingMongoConverter).isTrue();
} }
@Test // DATAMONGO-1912 @Test // DATAMONGO-1912
public void autogeneratesIdForMap() { void autogeneratesIdForMap() {
ReactiveMongoTemplate template = spy(this.template); ReactiveMongoTemplate template = spy(this.template);
doReturn(Mono.just(new ObjectId())).when(template).saveDocument(any(String.class), any(Document.class), doReturn(Mono.just(new ObjectId())).when(template).saveDocument(any(String.class), any(Document.class),
@ -217,7 +218,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1311 @Test // DATAMONGO-1311
public void executeQueryShouldUseBatchSizeWhenPresent() { void executeQueryShouldUseBatchSizeWhenPresent() {
when(findPublisher.batchSize(anyInt())).thenReturn(findPublisher); when(findPublisher.batchSize(anyInt())).thenReturn(findPublisher);
@ -228,7 +229,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void findShouldUseCollationWhenPresent() { void findShouldUseCollationWhenPresent() {
template.find(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); template.find(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe();
@ -237,7 +238,7 @@ public class ReactiveMongoTemplateUnitTests {
// //
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void findOneShouldUseCollationWhenPresent() { void findOneShouldUseCollationWhenPresent() {
template.findOne(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); template.findOne(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe();
@ -245,7 +246,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void existsShouldUseCollationWhenPresent() { void existsShouldUseCollationWhenPresent() {
template.exists(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe(); template.exists(new BasicQuery("{}").collation(Collation.of("fr")), AutogenerateableId.class).subscribe();
@ -253,7 +254,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void findAndModfiyShoudUseCollationWhenPresent() { void findAndModfiyShoudUseCollationWhenPresent() {
when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty());
@ -267,7 +268,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void findAndRemoveShouldUseCollationWhenPresent() { void findAndRemoveShouldUseCollationWhenPresent() {
when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(Mono.empty()); when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(Mono.empty());
@ -280,7 +281,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void findAndRemoveManyShouldUseCollationWhenPresent() { void findAndRemoveManyShouldUseCollationWhenPresent() {
when(collection.deleteMany(any(Bson.class), any())).thenReturn(Mono.empty()); when(collection.deleteMany(any(Bson.class), any())).thenReturn(Mono.empty());
@ -294,7 +295,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void updateOneShouldUseCollationWhenPresent() { void updateOneShouldUseCollationWhenPresent() {
when(collection.updateOne(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); when(collection.updateOne(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty());
@ -308,7 +309,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void updateManyShouldUseCollationWhenPresent() { void updateManyShouldUseCollationWhenPresent() {
when(collection.updateMany(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty()); when(collection.updateMany(any(Bson.class), any(Bson.class), any())).thenReturn(Mono.empty());
@ -323,7 +324,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518 @Test // DATAMONGO-1518
public void replaceOneShouldUseCollationWhenPresent() { void replaceOneShouldUseCollationWhenPresent() {
when(collection.replaceOne(any(Bson.class), any(), any(ReplaceOptions.class))).thenReturn(Mono.empty()); when(collection.replaceOne(any(Bson.class), any(), any(ReplaceOptions.class))).thenReturn(Mono.empty());
@ -337,7 +338,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518, DATAMONGO-2257 @Test // DATAMONGO-1518, DATAMONGO-2257
public void mapReduceShouldUseCollationWhenPresent() { void mapReduceShouldUseCollationWhenPresent() {
template.mapReduce(new BasicQuery("{}"), AutogenerateableId.class, AutogenerateableId.class, "", "", template.mapReduce(new BasicQuery("{}"), AutogenerateableId.class, AutogenerateableId.class, "", "",
MapReduceOptions.options().collation(Collation.of("fr"))).subscribe(); MapReduceOptions.options().collation(Collation.of("fr"))).subscribe();
@ -346,7 +347,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1518, DATAMONGO-2264 @Test // DATAMONGO-1518, DATAMONGO-2264
public void geoNearShouldUseCollationWhenPresent() { void geoNearShouldUseCollationWhenPresent() {
NearQuery query = NearQuery.near(0D, 0D).query(new BasicQuery("{}").collation(Collation.of("fr"))); NearQuery query = NearQuery.near(0D, 0D).query(new BasicQuery("{}").collation(Collation.of("fr")));
template.geoNear(query, AutogenerateableId.class).subscribe(); template.geoNear(query, AutogenerateableId.class).subscribe();
@ -355,7 +356,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() { void appliesFieldsWhenInterfaceProjectionIsClosedAndQueryDoesNotDefineFields() {
template.doFind("star-wars", new Document(), new Document(), Person.class, PersonProjection.class, template.doFind("star-wars", new Document(), new Document(), Person.class, PersonProjection.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -364,7 +365,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() { void doesNotApplyFieldsWhenInterfaceProjectionIsClosedAndQueryDefinesFields() {
template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, PersonProjection.class, template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, PersonProjection.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -373,7 +374,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() { void doesNotApplyFieldsWhenInterfaceProjectionIsOpen() {
template.doFind("star-wars", new Document(), new Document(), Person.class, PersonSpELProjection.class, template.doFind("star-wars", new Document(), new Document(), Person.class, PersonSpELProjection.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -382,7 +383,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719, DATAMONGO-2041 @Test // DATAMONGO-1719, DATAMONGO-2041
public void appliesFieldsToDtoProjection() { void appliesFieldsToDtoProjection() {
template.doFind("star-wars", new Document(), new Document(), Person.class, Jedi.class, template.doFind("star-wars", new Document(), new Document(), Person.class, Jedi.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -391,7 +392,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() { void doesNotApplyFieldsToDtoProjectionWhenQueryDefinesFields() {
template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, Jedi.class, template.doFind("star-wars", new Document(), new Document("bar", 1), Person.class, Jedi.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -400,7 +401,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void doesNotApplyFieldsWhenTargetIsNotAProjection() { void doesNotApplyFieldsWhenTargetIsNotAProjection() {
template.doFind("star-wars", new Document(), new Document(), Person.class, Person.class, template.doFind("star-wars", new Document(), new Document(), Person.class, Person.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -409,7 +410,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1719 @Test // DATAMONGO-1719
public void doesNotApplyFieldsWhenTargetExtendsDomainType() { void doesNotApplyFieldsWhenTargetExtendsDomainType() {
template.doFind("star-wars", new Document(), new Document(), Person.class, PersonExtended.class, template.doFind("star-wars", new Document(), new Document(), Person.class, PersonExtended.class,
FindPublisherPreparer.NO_OP_PREPARER).subscribe(); FindPublisherPreparer.NO_OP_PREPARER).subscribe();
@ -418,7 +419,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1783 @Test // DATAMONGO-1783
public void countShouldUseSkipFromQuery() { void countShouldUseSkipFromQuery() {
template.count(new Query().skip(10), Person.class, "star-wars").subscribe(); template.count(new Query().skip(10), Person.class, "star-wars").subscribe();
@ -429,7 +430,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1783 @Test // DATAMONGO-1783
public void countShouldUseLimitFromQuery() { void countShouldUseLimitFromQuery() {
template.count(new Query().limit(100), Person.class, "star-wars").subscribe(); template.count(new Query().limit(100), Person.class, "star-wars").subscribe();
@ -440,7 +441,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2360 @Test // DATAMONGO-2360
public void countShouldApplyQueryHintIfPresent() { void countShouldApplyQueryHintIfPresent() {
Document queryHint = new Document("age", 1); Document queryHint = new Document("age", 1);
template.count(new Query().withHint(queryHint), Person.class, "star-wars").subscribe(); template.count(new Query().withHint(queryHint), Person.class, "star-wars").subscribe();
@ -452,7 +453,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2365 @Test // DATAMONGO-2365
public void countShouldApplyQueryHintAsIndexNameIfPresent() { void countShouldApplyQueryHintAsIndexNameIfPresent() {
template.count(new Query().withHint("idx-1"), Person.class, "star-wars").subscribe(); template.count(new Query().withHint("idx-1"), Person.class, "star-wars").subscribe();
@ -463,7 +464,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2215 @Test // DATAMONGO-2215
public void updateShouldApplyArrayFilters() { void updateShouldApplyArrayFilters() {
template.updateFirst(new BasicQuery("{}"), template.updateFirst(new BasicQuery("{}"),
new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)),
@ -477,7 +478,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2215 @Test // DATAMONGO-2215
public void findAndModifyShouldApplyArrayFilters() { void findAndModifyShouldApplyArrayFilters() {
template.findAndModify(new BasicQuery("{}"), template.findAndModify(new BasicQuery("{}"),
new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)), new Update().set("grades.$[element]", 100).filterArray(Criteria.where("element").gte(100)),
@ -491,7 +492,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findShouldNotUseCollationWhenNoDefaultPresent() { void findShouldNotUseCollationWhenNoDefaultPresent() {
template.find(new BasicQuery("{'foo' : 'bar'}"), Jedi.class).subscribe(); template.find(new BasicQuery("{'foo' : 'bar'}"), Jedi.class).subscribe();
@ -499,7 +500,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findShouldUseDefaultCollationWhenPresent() { void findShouldUseDefaultCollationWhenPresent() {
template.find(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe(); template.find(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe();
@ -507,7 +508,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findOneShouldUseDefaultCollationWhenPresent() { void findOneShouldUseDefaultCollationWhenPresent() {
template.findOne(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe(); template.findOne(new BasicQuery("{'foo' : 'bar'}"), Sith.class).subscribe();
@ -515,7 +516,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void existsShouldUseDefaultCollationWhenPresent() { void existsShouldUseDefaultCollationWhenPresent() {
template.exists(new BasicQuery("{}"), Sith.class).subscribe(); template.exists(new BasicQuery("{}"), Sith.class).subscribe();
@ -523,7 +524,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findAndModfiyShoudUseDefaultCollationWhenPresent() { void findAndModfiyShoudUseDefaultCollationWhenPresent() {
template.findAndModify(new BasicQuery("{}"), new Update(), Sith.class).subscribe(); template.findAndModify(new BasicQuery("{}"), new Update(), Sith.class).subscribe();
@ -535,7 +536,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findAndRemoveShouldUseDefaultCollationWhenPresent() { void findAndRemoveShouldUseDefaultCollationWhenPresent() {
template.findAndRemove(new BasicQuery("{}"), Sith.class).subscribe(); template.findAndRemove(new BasicQuery("{}"), Sith.class).subscribe();
@ -547,7 +548,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void createCollectionShouldNotCollationIfNotPresent() { void createCollectionShouldNotCollationIfNotPresent() {
template.createCollection(AutogenerateableId.class).subscribe(); template.createCollection(AutogenerateableId.class).subscribe();
@ -558,7 +559,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void createCollectionShouldApplyDefaultCollation() { void createCollectionShouldApplyDefaultCollation() {
template.createCollection(Sith.class).subscribe(); template.createCollection(Sith.class).subscribe();
@ -570,7 +571,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() { void createCollectionShouldFavorExplicitOptionsOverDefaultCollation() {
template.createCollection(Sith.class, CollectionOptions.just(Collation.of("en_US"))).subscribe(); template.createCollection(Sith.class, CollectionOptions.just(Collation.of("en_US"))).subscribe();
@ -582,7 +583,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() { void createCollectionShouldUseDefaultCollationIfCollectionOptionsAreNull() {
template.createCollection(Sith.class, null).subscribe(); template.createCollection(Sith.class, null).subscribe();
@ -594,7 +595,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void aggreateShouldUseDefaultCollationIfPresent() { void aggreateShouldUseDefaultCollationIfPresent() {
template.aggregate(newAggregation(Sith.class, project("id")), AutogenerateableId.class, Document.class).subscribe(); template.aggregate(newAggregation(Sith.class, project("id")), AutogenerateableId.class, Document.class).subscribe();
@ -602,7 +603,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() { void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent() {
template template
.aggregate( .aggregate(
@ -615,7 +616,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2153 @Test // DATAMONGO-2153
public void aggregateShouldHonorOptionsComment() { void aggregateShouldHonorOptionsComment() {
AggregationOptions options = AggregationOptions.builder().comment("expensive").build(); AggregationOptions options = AggregationOptions.builder().comment("expensive").build();
@ -626,7 +627,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2390 @Test // DATAMONGO-2390
public void aggregateShouldNoApplyZeroOrNegativeMaxTime() { void aggregateShouldNoApplyZeroOrNegativeMaxTime() {
template template
.aggregate(newAggregation(MongoTemplateUnitTests.Sith.class, project("id")).withOptions( .aggregate(newAggregation(MongoTemplateUnitTests.Sith.class, project("id")).withOptions(
@ -643,7 +644,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2390 @Test // DATAMONGO-2390
public void aggregateShouldApplyMaxTimeIfSet() { void aggregateShouldApplyMaxTimeIfSet() {
template template
.aggregate( .aggregate(
@ -656,7 +657,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findAndReplaceShouldUseCollationWhenPresent() { void findAndReplaceShouldUseCollationWhenPresent() {
template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new Jedi()).subscribe(); template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new Jedi()).subscribe();
@ -667,7 +668,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findAndReplaceShouldUseDefaultCollationWhenPresent() { void findAndReplaceShouldUseDefaultCollationWhenPresent() {
template.findAndReplace(new BasicQuery("{}"), new Sith()).subscribe(); template.findAndReplace(new BasicQuery("{}"), new Sith()).subscribe();
@ -678,7 +679,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() { void findAndReplaceShouldUseCollationEvenIfDefaultCollationIsPresent() {
template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new MongoTemplateUnitTests.Sith()) template.findAndReplace(new BasicQuery("{}").collation(Collation.of("fr")), new MongoTemplateUnitTests.Sith())
.subscribe(); .subscribe();
@ -690,7 +691,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findDistinctShouldUseDefaultCollationWhenPresent() { void findDistinctShouldUseDefaultCollationWhenPresent() {
template.findDistinct(new BasicQuery("{}"), "name", Sith.class, String.class).subscribe(); template.findDistinct(new BasicQuery("{}"), "name", Sith.class, String.class).subscribe();
@ -698,7 +699,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void findDistinctPreferCollationFromQueryOverDefaultCollation() { void findDistinctPreferCollationFromQueryOverDefaultCollation() {
template.findDistinct(new BasicQuery("{}").collation(Collation.of("fr")), "name", Sith.class, String.class) template.findDistinct(new BasicQuery("{}").collation(Collation.of("fr")), "name", Sith.class, String.class)
.subscribe(); .subscribe();
@ -707,7 +708,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void updateFirstShouldUseDefaultCollationWhenPresent() { void updateFirstShouldUseDefaultCollationWhenPresent() {
template.updateFirst(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe(); template.updateFirst(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe();
@ -719,7 +720,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void updateFirstShouldPreferExplicitCollationOverDefaultCollation() { void updateFirstShouldPreferExplicitCollationOverDefaultCollation() {
template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class) template.updateFirst(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class)
.subscribe(); .subscribe();
@ -732,7 +733,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void updateMultiShouldUseDefaultCollationWhenPresent() { void updateMultiShouldUseDefaultCollationWhenPresent() {
template.updateMulti(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe(); template.updateMulti(new BasicQuery("{}"), Update.update("foo", "bar"), Sith.class).subscribe();
@ -744,7 +745,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void updateMultiShouldPreferExplicitCollationOverDefaultCollation() { void updateMultiShouldPreferExplicitCollationOverDefaultCollation() {
template.updateMulti(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class) template.updateMulti(new BasicQuery("{}").collation(Collation.of("fr")), Update.update("foo", "bar"), Sith.class)
.subscribe(); .subscribe();
@ -757,7 +758,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void removeShouldUseDefaultCollationWhenPresent() { void removeShouldUseDefaultCollationWhenPresent() {
template.remove(new BasicQuery("{}"), Sith.class).subscribe(); template.remove(new BasicQuery("{}"), Sith.class).subscribe();
@ -769,7 +770,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-1854 @Test // DATAMONGO-1854
public void removeShouldPreferExplicitCollationOverDefaultCollation() { void removeShouldPreferExplicitCollationOverDefaultCollation() {
template.remove(new BasicQuery("{}").collation(Collation.of("fr")), Sith.class).subscribe(); template.remove(new BasicQuery("{}").collation(Collation.of("fr")), Sith.class).subscribe();
@ -781,7 +782,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void saveShouldInvokeCallbacks() { void saveShouldInvokeCallbacks() {
ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback());
ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback());
@ -799,7 +800,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void insertShouldInvokeCallbacks() { void insertShouldInvokeCallbacks() {
ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback());
ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback());
@ -817,7 +818,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void insertAllShouldInvokeCallbacks() { void insertAllShouldInvokeCallbacks() {
ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback());
ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback());
@ -839,7 +840,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void findAndReplaceShouldInvokeCallbacks() { void findAndReplaceShouldInvokeCallbacks() {
ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback()); ValueCapturingBeforeConvertCallback beforeConvertCallback = spy(new ValueCapturingBeforeConvertCallback());
ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback()); ValueCapturingBeforeSaveCallback beforeSaveCallback = spy(new ValueCapturingBeforeSaveCallback());
@ -857,12 +858,12 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void entityCallbacksAreNotSetByDefault() { void entityCallbacksAreNotSetByDefault() {
Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isNull(); Assertions.assertThat(ReflectionTestUtils.getField(template, "entityCallbacks")).isNull();
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() { void entityCallbacksShouldBeInitiatedOnSettingApplicationContext() {
ApplicationContext ctx = new StaticApplicationContext(); ApplicationContext ctx = new StaticApplicationContext();
template.setApplicationContext(ctx); template.setApplicationContext(ctx);
@ -871,7 +872,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void setterForEntityCallbackOverridesContextInitializedOnes() { void setterForEntityCallbackOverridesContextInitializedOnes() {
ApplicationContext ctx = new StaticApplicationContext(); ApplicationContext ctx = new StaticApplicationContext();
template.setApplicationContext(ctx); template.setApplicationContext(ctx);
@ -883,7 +884,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2261 @Test // DATAMONGO-2261
public void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() { void setterForApplicationContextShouldNotOverrideAlreadySetEntityCallbacks() {
ReactiveEntityCallbacks callbacks = ReactiveEntityCallbacks.create(); ReactiveEntityCallbacks callbacks = ReactiveEntityCallbacks.create();
ApplicationContext ctx = new StaticApplicationContext(); ApplicationContext ctx = new StaticApplicationContext();
@ -895,7 +896,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2344 @Test // DATAMONGO-2344
public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() { void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFind() {
template.find(new Query().slaveOk(), AutogenerateableId.class).subscribe(); template.find(new Query().slaveOk(), AutogenerateableId.class).subscribe();
@ -903,7 +904,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2344 @Test // DATAMONGO-2344
public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() { void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindOne() {
template.findOne(new Query().slaveOk(), AutogenerateableId.class).subscribe(); template.findOne(new Query().slaveOk(), AutogenerateableId.class).subscribe();
@ -911,7 +912,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2344 @Test // DATAMONGO-2344
public void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() { void slaveOkQueryOptionShouldApplyPrimaryPreferredReadPreferenceForFindDistinct() {
template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class).subscribe(); template.findDistinct(new Query().slaveOk(), "name", AutogenerateableId.class, String.class).subscribe();
@ -919,7 +920,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2331 @Test // DATAMONGO-2331
public void updateShouldAllowAggregationExpressions() { void updateShouldAllowAggregationExpressions() {
AggregationUpdate update = AggregationUpdate.update().set("total") AggregationUpdate update = AggregationUpdate.update().set("total")
.toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2"));
@ -935,7 +936,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2331 @Test // DATAMONGO-2331
public void updateShouldAllowMultipleAggregationExpressions() { void updateShouldAllowMultipleAggregationExpressions() {
AggregationUpdate update = AggregationUpdate.update() // AggregationUpdate update = AggregationUpdate.update() //
.set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) // .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) //
@ -963,7 +964,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2331 @Test // DATAMONGO-2331
public void updateShouldMapAggregationExpressionToDomainType() { void updateShouldMapAggregationExpressionToDomainType() {
AggregationUpdate update = AggregationUpdate.update().set("name") AggregationUpdate update = AggregationUpdate.update().set("name")
.toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2"));
@ -979,7 +980,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2331 @Test // DATAMONGO-2331
public void updateShouldPassOnUnsetCorrectly() { void updateShouldPassOnUnsetCorrectly() {
SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments") SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments")
.toValue(Fields.fields("misc1").and("misc2").asList()); .toValue(Fields.fields("misc1").and("misc2").asList());
@ -999,7 +1000,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2331 @Test // DATAMONGO-2331
public void updateShouldMapAggregationUnsetToDomainType() { void updateShouldMapAggregationUnsetToDomainType() {
AggregationUpdate update = AggregationUpdate.update(); AggregationUpdate update = AggregationUpdate.update();
update.unset("name"); update.unset("name");
@ -1110,163 +1111,138 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findShouldInvokeAfterConvertCallbacks() { void findShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.find(Document.class)).thenReturn(findPublisher); when(collection.find(Document.class)).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
List<Person> results = template.find(new Query(), Person.class).timeout(Duration.ofSeconds(1)) List<Person> results = template.find(new Query(), Person.class).timeout(Duration.ofSeconds(1)).toStream()
.toStream().collect(Collectors.toList()); .collect(Collectors.toList());
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(results.get(0).id).isEqualTo("after-convert"); assertThat(results.get(0).id).isEqualTo("after-convert");
} }
private Document initialLukeDocument() {
return new Document(ImmutableMap.of(
"_id", "init",
"firstname", "luke"
));
}
private Person initialLuke() {
Person expectedEnitty = new Person();
expectedEnitty.id = "init";
expectedEnitty.firstname = "luke";
return expectedEnitty;
}
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findByIdShouldInvokeAfterConvertCallbacks() { void findByIdShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
Person result = template.findById("init", Person.class).block(Duration.ofSeconds(1)); Person result = template.findById("init", Person.class).block(Duration.ofSeconds(1));
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(result.id).isEqualTo("after-convert"); assertThat(result.id).isEqualTo("after-convert");
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findOneShouldInvokeAfterConvertCallbacks() { void findOneShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher); when(collection.find(any(Bson.class), eq(Document.class))).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
Person result = template.findOne(new Query(), Person.class).block(Duration.ofSeconds(1)); Person result = template.findOne(new Query(), Person.class).block(Duration.ofSeconds(1));
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(result.id).isEqualTo("after-convert"); assertThat(result.id).isEqualTo("after-convert");
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAllShouldInvokeAfterConvertCallbacks() { void findAllShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.find(Document.class)).thenReturn(findPublisher); when(collection.find(Document.class)).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
List<Person> results = template.findAll(Person.class).timeout(Duration.ofSeconds(1)) List<Person> results = template.findAll(Person.class).timeout(Duration.ofSeconds(1)).toStream()
.toStream().collect(Collectors.toList()); .collect(Collectors.toList());
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(results.get(0).id).isEqualTo("after-convert"); assertThat(results.get(0).id).isEqualTo("after-convert");
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAndModifyShouldInvokeAfterConvertCallbacks() { void findAndModifyShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(findPublisher); when(collection.findOneAndUpdate(any(Bson.class), any(Bson.class), any())).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
Person result = template.findAndModify(new Query(), new Update(), Person.class).block(Duration.ofSeconds(1)); Person result = template.findAndModify(new Query(), new Update(), Person.class).block(Duration.ofSeconds(1));
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(result.id).isEqualTo("after-convert"); assertThat(result.id).isEqualTo("after-convert");
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAndRemoveShouldInvokeAfterConvertCallbacks() { void findAndRemoveShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(findPublisher); when(collection.findOneAndDelete(any(Bson.class), any())).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
Person result = template.findAndRemove(new Query(), Person.class).block(Duration.ofSeconds(1)); Person result = template.findAndRemove(new Query(), Person.class).block(Duration.ofSeconds(1));
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(result.id).isEqualTo("after-convert"); assertThat(result.id).isEqualTo("after-convert");
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAllAndRemoveShouldInvokeAfterConvertCallbacks() { void findAllAndRemoveShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.find(Document.class)).thenReturn(findPublisher); when(collection.find(Document.class)).thenReturn(findPublisher);
makeFindPublisherPublishJust(document); stubFindSubscribe(document);
when(collection.deleteMany(any(Bson.class), any(DeleteOptions.class))) when(collection.deleteMany(any(Bson.class), any(DeleteOptions.class)))
.thenReturn(Mono.just(spy(DeleteResult.class))); .thenReturn(Mono.just(spy(DeleteResult.class)));
List<Person> results = template.findAllAndRemove(new Query(), Person.class).timeout(Duration.ofSeconds(1)) List<Person> results = template.findAllAndRemove(new Query(), Person.class).timeout(Duration.ofSeconds(1))
.toStream().collect(Collectors.toList()); .toStream().collect(Collectors.toList());
verify(afterConvertCallback).onAfterConvert(eq(initialLuke()), eq(document), anyString()); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(document), anyString());
assertThat(results.get(0).id).isEqualTo("after-convert"); assertThat(results.get(0).id).isEqualTo("after-convert");
} }
private void makeFindPublisherPublishJust(Document document) {
Publisher<Document> realPublisher = Flux.just(document);
doAnswer(invocation -> {
Subscriber<Document> subscriber = invocation.getArgument(0);
realPublisher.subscribe(subscriber);
return null;
}).when(findPublisher).subscribe(any());
}
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAndReplaceShouldInvokeAfterConvertCallbacks() { void findAndReplaceShouldInvokeAfterConvertCallbacks() {
ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback));
when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher);
makeFindPublisherPublishJust(initialLukeDocument()); stubFindSubscribe(new Document("_id", "init").append("firstname", "luke"));
Person entity = new Person(); Person entity = new Person();
entity.id = "init"; entity.id = "init";
@ -1279,7 +1255,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void saveShouldInvokeAfterSaveCallbacks() { void saveShouldInvokeAfterSaveCallbacks() {
ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback());
@ -1288,7 +1264,7 @@ public class ReactiveMongoTemplateUnitTests {
when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class))) when(collection.replaceOne(any(Bson.class), any(Document.class), any(ReplaceOptions.class)))
.thenReturn(Mono.just(mock(UpdateResult.class))); .thenReturn(Mono.just(mock(UpdateResult.class)));
Person entity = initialLuke(); Person entity = new Person("init", "luke");
Person saved = template.save(entity).block(Duration.ofSeconds(1)); Person saved = template.save(entity).block(Duration.ofSeconds(1));
@ -1297,7 +1273,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void insertShouldInvokeAfterSaveCallbacks() { void insertShouldInvokeAfterSaveCallbacks() {
ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback());
@ -1305,7 +1281,7 @@ public class ReactiveMongoTemplateUnitTests {
when(collection.insertOne(any())).thenReturn(Mono.just(mock(InsertOneResult.class))); when(collection.insertOne(any())).thenReturn(Mono.just(mock(InsertOneResult.class)));
Person entity = initialLuke(); Person entity = new Person("init", "luke");
Person saved = template.insert(entity).block(Duration.ofSeconds(1)); Person saved = template.insert(entity).block(Duration.ofSeconds(1));
@ -1314,7 +1290,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void insertAllShouldInvokeAfterSaveCallbacks() { void insertAllShouldInvokeAfterSaveCallbacks() {
ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback());
@ -1333,9 +1309,8 @@ public class ReactiveMongoTemplateUnitTests {
return Flux.fromIterable(list).map(i -> mock(InsertManyResult.class)); return Flux.fromIterable(list).map(i -> mock(InsertManyResult.class));
}); });
List<Person> saved = template.insertAll(Arrays.asList(entity1, entity2)) List<Person> saved = template.insertAll(Arrays.asList(entity1, entity2)).timeout(Duration.ofSeconds(1)).toStream()
.timeout(Duration.ofSeconds(1)) .collect(Collectors.toList());
.toStream().collect(Collectors.toList());
verify(afterSaveCallback, times(2)).onAfterSave(any(), any(), anyString()); verify(afterSaveCallback, times(2)).onAfterSave(any(), any(), anyString());
assertThat(saved.get(0).id).isEqualTo("after-save"); assertThat(saved.get(0).id).isEqualTo("after-save");
@ -1343,16 +1318,16 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAndReplaceShouldInvokeAfterSaveCallbacks() { void findAndReplaceShouldInvokeAfterSaveCallbacks() {
ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback());
template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback));
when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(findPublisher);
makeFindPublisherPublishJust(initialLukeDocument()); stubFindSubscribe(new Document("_id", "init").append("firstname", "luke"));
Person entity = initialLuke(); Person entity = new Person("init", "luke");
Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1));
@ -1361,7 +1336,7 @@ public class ReactiveMongoTemplateUnitTests {
} }
@Test // DATAMONGO-2479 @Test // DATAMONGO-2479
public void findAndReplaceShouldEmitAfterSaveEvent() { void findAndReplaceShouldEmitAfterSaveEvent() {
AbstractMongoEventListener<Person> eventListener = new AbstractMongoEventListener<Person>() { AbstractMongoEventListener<Person> eventListener = new AbstractMongoEventListener<Person>() {
@ -1379,9 +1354,9 @@ public class ReactiveMongoTemplateUnitTests {
template.setApplicationContext(ctx); template.setApplicationContext(ctx);
Person entity = initialLuke(); Person entity = new Person("init", "luke");
Document document = initialLukeDocument(); Document document = new Document("_id", "init").append("firstname", "luke");
when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(Mono.just(document)); when(collection.findOneAndReplace(any(Bson.class), any(Document.class), any())).thenReturn(Mono.just(document));
Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1)); Person saved = template.findAndReplace(new Query(), entity).block(Duration.ofSeconds(1));
@ -1389,8 +1364,21 @@ public class ReactiveMongoTemplateUnitTests {
assertThat(saved.id).isEqualTo("after-save-event"); assertThat(saved.id).isEqualTo("after-save-event");
} }
private void stubFindSubscribe(Document document) {
Publisher<Document> realPublisher = Flux.just(document);
doAnswer(invocation -> {
Subscriber<Document> subscriber = invocation.getArgument(0);
realPublisher.subscribe(subscriber);
return null;
}).when(findPublisher).subscribe(any());
}
@Data @Data
@org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars") @org.springframework.data.mongodb.core.mapping.Document(collection = "star-wars")
@AllArgsConstructor
@NoArgsConstructor
static class Person { static class Person {
@Id String id; @Id String id;
@ -1480,10 +1468,12 @@ public class ReactiveMongoTemplateUnitTests {
public Mono<Person> onAfterConvert(Person entity, Document document, String collection) { public Mono<Person> onAfterConvert(Person entity, Document document, String collection) {
capture(entity); capture(entity);
return Mono.just(new Person() {{ return Mono.just(new Person() {
{
id = "after-convert"; id = "after-convert";
firstname = entity.firstname; firstname = entity.firstname;
}}); }
});
} }
} }
@ -1494,10 +1484,12 @@ public class ReactiveMongoTemplateUnitTests {
public Mono<Person> onAfterSave(Person entity, Document document, String collection) { public Mono<Person> onAfterSave(Person entity, Document document, String collection) {
capture(entity); capture(entity);
return Mono.just(new Person() {{ return Mono.just(new Person() {
{
id = "after-save"; id = "after-save";
firstname = entity.firstname; firstname = entity.firstname;
}}); }
});
} }
} }

12
src/main/asciidoc/reference/mongo-entity-callbacks.adoc

@ -16,6 +16,12 @@ Spring Data MongoDB uses the `EntityCallback` API for its auditing support and r
| Invoked before a domain object is converted to `org.bson.Document`. | Invoked before a domain object is converted to `org.bson.Document`.
| `Ordered.LOWEST_PRECEDENCE` | `Ordered.LOWEST_PRECEDENCE`
| Reactive/AfterConvertCallback
| `onAfterConvert(T entity, org.bson.Document target, String collection)`
| Invoked after a domain object is loaded. +
Can modify the domain object after reading it from a `org.bson.Document`.
| `Ordered.LOWEST_PRECEDENCE`
| Reactive/AuditingEntityCallback | Reactive/AuditingEntityCallback
| `onBeforeConvert(Object entity, String collection)` | `onBeforeConvert(Object entity, String collection)`
| Marks an auditable entity _created_ or _modified_ | Marks an auditable entity _created_ or _modified_
@ -27,5 +33,11 @@ Spring Data MongoDB uses the `EntityCallback` API for its auditing support and r
Can modify the target, to be persisted, `Document` containing all mapped entity information. Can modify the target, to be persisted, `Document` containing all mapped entity information.
| `Ordered.LOWEST_PRECEDENCE` | `Ordered.LOWEST_PRECEDENCE`
| Reactive/AfterSaveCallback
| `onAfterSave(T entity, org.bson.Document target, String collection)`
| Invoked before a domain object is saved. +
Can modify the domain object, to be returned after save, `Document` containing all mapped entity information.
| `Ordered.LOWEST_PRECEDENCE`
|=== |===

Loading…
Cancel
Save