Add missing hooks for callbacks. (#1142)
1) the previous change (#955) to CouchbaseAuditingRegister intended to register AuditingEntityCallback instead of AuditingEventListener but only changed the name that AuditingEventListener was registered with. Since AuditingEventListener does exactly the same thing as AuditingEntityCallback, it behaved as those AuditingEntityCallback was being used. 2) It seems that the two mechanisms - EntityCallback and EventListener both do more-or-less the same thing. I'm not sure why there are two mechanisms to do the same thing. 3) Although the ReactiveAuditingEntityCallback mechanism is triggered only for reactive operations and the non-reactive AuditingEntityCallback is triggered only for non-reactive operations, the events are triggered for both. Since there was a desire to have distinct callbacks for reactive/non-reactive operations, I also made distinct events for reactive/non-reactive operations. However both the reactive and non-reactive event mechanisms are triggered for either reactive and non-reactive operations, so it is necessary for the mechanism to determine if it should act on the event. 4) Although there is an AbstractCouchbaseEventListener that is extended by LoggingEventListener and ValidatingEventListener, AuditingEventListener does not extend it (maybe it should). Closes #1074. Co-authored-by: mikereiche <michael.reiche@couchbase.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.mapping.event.AfterConvertCallback;
|
||||
import org.springframework.data.couchbase.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeConvertCallback;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeSaveEvent;
|
||||
@@ -95,16 +96,21 @@ class CouchbaseTemplateSupport implements ApplicationContextAware, TemplateSuppo
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object applyUpdatedCas(final Object entity, final long cas) {
|
||||
public Object applyUpdatedCas(final Object entity, CouchbaseDocument converted, final long cas) {
|
||||
Object returnValue;
|
||||
final ConvertingPropertyAccessor<Object> accessor = getPropertyAccessor(entity);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
|
||||
if (versionProperty != null) {
|
||||
accessor.setProperty(versionProperty, cas);
|
||||
return accessor.getBean();
|
||||
returnValue = accessor.getBean();
|
||||
} else {
|
||||
returnValue = entity;
|
||||
}
|
||||
return entity;
|
||||
maybeEmitEvent(new AfterSaveEvent(returnValue, converted));
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,7 +178,7 @@ class CouchbaseTemplateSupport implements ApplicationContextAware, TemplateSuppo
|
||||
this.entityCallbacks = entityCallbacks;
|
||||
}
|
||||
|
||||
void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
|
||||
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
|
||||
if (canPublishEvent()) {
|
||||
try {
|
||||
this.applicationContext.publishEvent(event);
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
@@ -44,8 +45,8 @@ public class NonReactiveSupportWrapper implements ReactiveTemplateSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> applyUpdatedCas(Object entity, long cas) {
|
||||
return Mono.fromSupplier(() -> support.applyUpdatedCas(entity, cas));
|
||||
public Mono<Object> applyUpdatedCas(Object entity, CouchbaseDocument converted, long cas) {
|
||||
return Mono.fromSupplier(() -> support.applyUpdatedCas(entity, converted, cas));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,4 +63,9 @@ public class NonReactiveSupportWrapper implements ReactiveTemplateSupport {
|
||||
public String getJavaNameForEntity(Class<?> clazz) {
|
||||
return support.getJavaNameForEntity(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
|
||||
support.maybeEmitEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveAfterSaveEvent;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -26,11 +30,11 @@ import org.springframework.data.couchbase.core.convert.translation.TranslationSe
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveAfterConvertCallback;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveBeforeConvertCallback;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveBeforeConvertEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveBeforeSaveEvent;
|
||||
import org.springframework.data.couchbase.repository.support.MappingCouchbaseEntityInformation;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
@@ -38,7 +42,6 @@ import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Internal encode/decode support for {@link ReactiveCouchbaseTemplate}.
|
||||
@@ -65,16 +68,13 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
|
||||
@Override
|
||||
public Mono<CouchbaseDocument> encodeEntity(final Object entityToEncode) {
|
||||
return Mono.just(entityToEncode)
|
||||
.doOnNext(entity -> maybeEmitEvent(new BeforeConvertEvent<>(entity)))
|
||||
.flatMap(entity -> maybeCallBeforeConvert(entity, ""))
|
||||
.map(maybeNewEntity -> {
|
||||
return Mono.just(entityToEncode).doOnNext(entity -> maybeEmitEvent(new ReactiveBeforeConvertEvent<>(entity)))
|
||||
.flatMap(entity -> maybeCallBeforeConvert(entity, "")).map(maybeNewEntity -> {
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
converter.write(maybeNewEntity, converted);
|
||||
return converted;
|
||||
})
|
||||
.flatMap(converted -> maybeCallAfterConvert(entityToEncode, converted, "").thenReturn(converted))
|
||||
.doOnNext(converted -> maybeEmitEvent(new BeforeSaveEvent<>(entityToEncode, converted)));
|
||||
}).flatMap(converted -> maybeCallAfterConvert(entityToEncode, converted, "").thenReturn(converted))
|
||||
.doOnNext(converted -> maybeEmitEvent(new ReactiveBeforeSaveEvent<>(entityToEncode, converted)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,17 +98,22 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> applyUpdatedCas(final Object entity, final long cas) {
|
||||
public Mono<Object> applyUpdatedCas(final Object entity, CouchbaseDocument converted, final long cas) {
|
||||
return Mono.fromSupplier(() -> {
|
||||
Object returnValue;
|
||||
final ConvertingPropertyAccessor<Object> accessor = getPropertyAccessor(entity);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext
|
||||
.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
|
||||
if (versionProperty != null) {
|
||||
accessor.setProperty(versionProperty, cas);
|
||||
return accessor.getBean();
|
||||
returnValue = accessor.getBean();
|
||||
} else {
|
||||
returnValue = entity;
|
||||
}
|
||||
return entity;
|
||||
maybeEmitEvent(new ReactiveAfterSaveEvent(returnValue, converted));
|
||||
return returnValue;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -116,7 +121,8 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
public Mono<Object> applyUpdatedId(final Object entity, Object id) {
|
||||
return Mono.fromSupplier(() -> {
|
||||
final ConvertingPropertyAccessor<Object> accessor = getPropertyAccessor(entity);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext
|
||||
.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
@@ -130,8 +136,7 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
@Override
|
||||
public Long getCas(final Object entity) {
|
||||
final ConvertingPropertyAccessor<Object> accessor = getPropertyAccessor(entity);
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext
|
||||
.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(entity.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
|
||||
long cas = 0;
|
||||
@@ -166,9 +171,9 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ReactiveEntityCallbacks} instance to use when invoking {@link
|
||||
* org.springframework.data.mapping.callback.ReactiveEntityCallbacks callbacks} like the {@link
|
||||
* ReactiveBeforeConvertCallback}.
|
||||
* Set the {@link ReactiveEntityCallbacks} instance to use when invoking
|
||||
* {@link org.springframework.data.mapping.callback.ReactiveEntityCallbacks callbacks} like the
|
||||
* {@link ReactiveBeforeConvertCallback}.
|
||||
* <p/>
|
||||
* Overrides potentially existing {@link EntityCallbacks}.
|
||||
*
|
||||
@@ -180,7 +185,7 @@ class ReactiveCouchbaseTemplateSupport implements ApplicationContextAware, React
|
||||
this.reactiveEntityCallbacks = reactiveEntityCallbacks;
|
||||
}
|
||||
|
||||
void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
|
||||
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
|
||||
if (canPublishEvent()) {
|
||||
try {
|
||||
this.applicationContext.publishEvent(event);
|
||||
|
||||
@@ -78,16 +78,16 @@ public class ReactiveInsertByIdOperationSupport implements ReactiveInsertByIdOpe
|
||||
|
||||
@Override
|
||||
public Mono<T> one(T object) {
|
||||
PseudoArgs<InsertOptions> pArgs = new PseudoArgs(template, scope, collection,
|
||||
options != null ? options : InsertOptions.insertOptions());
|
||||
LOG.trace("statement: {} scope: {} collection: {} options: {}", "insertById", pArgs.getScope(),
|
||||
pArgs.getCollection(), pArgs.getOptions());
|
||||
PseudoArgs<InsertOptions> pArgs = new PseudoArgs(template, scope, collection,
|
||||
options != null ? options : InsertOptions.insertOptions());
|
||||
LOG.trace("statement: {} scope: {} collection: {} options: {}", "insertById", pArgs.getScope(),
|
||||
pArgs.getCollection(), pArgs.getOptions());
|
||||
return Mono.just(object).flatMap(support::encodeEntity)
|
||||
.flatMap(converted -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive()
|
||||
.insert(converted.getId(), converted.export(), buildOptions(pArgs.getOptions(), converted))
|
||||
.flatMap(converted -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive()
|
||||
.insert(converted.getId(), converted.export(), buildOptions(pArgs.getOptions(), converted))
|
||||
.flatMap(result -> support.applyUpdatedId(object, converted.getId())
|
||||
.flatMap(insertedObject -> (Mono<T>) support.applyUpdatedCas(insertedObject, result.cas()))))
|
||||
.flatMap(updatedObject -> support.applyUpdatedCas(updatedObject, converted, result.cas()))))
|
||||
.onErrorMap(throwable -> {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveAfterDeleteEvent;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveBeforeDeleteEvent;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -68,19 +70,22 @@ public class ReactiveRemoveByIdOperationSupport implements ReactiveRemoveByIdOpe
|
||||
|
||||
@Override
|
||||
public Mono<RemoveResult> one(final String id) {
|
||||
PseudoArgs<RemoveOptions> pArgs = new PseudoArgs(template, scope, collection,
|
||||
options != null ? options : RemoveOptions.removeOptions());
|
||||
return Mono.just(id)
|
||||
.flatMap(docId -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive().remove(id, buildRemoveOptions(pArgs.getOptions()))
|
||||
.map(r -> RemoveResult.from(docId, r)))
|
||||
.onErrorMap(throwable -> {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
|
||||
} else {
|
||||
return throwable;
|
||||
}
|
||||
});
|
||||
PseudoArgs<RemoveOptions> pArgs = new PseudoArgs(template, scope, collection,
|
||||
options != null ? options : RemoveOptions.removeOptions());
|
||||
return Mono.just(id).map(r -> {
|
||||
template.support().maybeEmitEvent(new ReactiveBeforeDeleteEvent<>(r));
|
||||
return r;
|
||||
}).flatMap(docId -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive().remove(id, buildRemoveOptions(pArgs.getOptions())).map(r -> {
|
||||
template.support().maybeEmitEvent(new ReactiveAfterDeleteEvent<>(r));
|
||||
return RemoveResult.from(docId, r);
|
||||
})).onErrorMap(throwable -> {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
|
||||
} else {
|
||||
return throwable;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -78,14 +78,14 @@ public class ReactiveReplaceByIdOperationSupport implements ReactiveReplaceByIdO
|
||||
|
||||
@Override
|
||||
public Mono<T> one(T object) {
|
||||
PseudoArgs<ReplaceOptions> pArgs = new PseudoArgs<>(template, scope, collection,
|
||||
options != null ? options : ReplaceOptions.replaceOptions());
|
||||
LOG.trace("statement: {} pArgs: {}", "replaceById", pArgs);
|
||||
return Mono.just(object).flatMap(support::encodeEntity).flatMap(converted -> template.getCouchbaseClientFactory()
|
||||
.withScope(pArgs.getScope()).getCollection(pArgs.getCollection()).reactive()
|
||||
.replace(converted.getId(), converted.export(), buildReplaceOptions(pArgs.getOptions(), object, converted))
|
||||
.flatMap(result -> support.applyUpdatedId(object, converted.getId())
|
||||
.flatMap(replacedObject -> (Mono<T>) support.applyUpdatedCas(replacedObject, result.cas()))))
|
||||
PseudoArgs<ReplaceOptions> pArgs = new PseudoArgs<>(template, scope, collection,
|
||||
options != null ? options : ReplaceOptions.replaceOptions());
|
||||
LOG.trace("statement: {} pArgs: {}", "replaceById", pArgs);
|
||||
return Mono.just(object).flatMap(support::encodeEntity)
|
||||
.flatMap(converted -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive()
|
||||
.replace(converted.getId(), converted.export(), buildReplaceOptions(pArgs.getOptions(), object, converted))
|
||||
.flatMap(result -> support.applyUpdatedCas(object, converted, result.cas())))
|
||||
.onErrorMap(throwable -> {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface ReactiveTemplateSupport {
|
||||
@@ -25,11 +26,13 @@ public interface ReactiveTemplateSupport {
|
||||
|
||||
<T> Mono<T> decodeEntity(String id, String source, long cas, Class<T> entityClass);
|
||||
|
||||
Mono<Object> applyUpdatedCas(Object entity, long cas);
|
||||
<T> Mono<T> applyUpdatedCas(T entity, CouchbaseDocument converted, long cas);
|
||||
|
||||
Mono<Object> applyUpdatedId(Object entity, Object id);
|
||||
<T> Mono<T> applyUpdatedId(T entity, Object id);
|
||||
|
||||
Long getCas(Object entity);
|
||||
|
||||
String getJavaNameForEntity(Class<?> clazz);
|
||||
|
||||
void maybeEmitEvent(CouchbaseMappingEvent<?> event);
|
||||
}
|
||||
|
||||
@@ -75,14 +75,14 @@ public class ReactiveUpsertByIdOperationSupport implements ReactiveUpsertByIdOpe
|
||||
|
||||
@Override
|
||||
public Mono<T> one(T object) {
|
||||
PseudoArgs<UpsertOptions> pArgs = new PseudoArgs<>(template, scope, collection,
|
||||
options != null ? options : UpsertOptions.upsertOptions());
|
||||
PseudoArgs<UpsertOptions> pArgs = new PseudoArgs<>(template, scope, collection,
|
||||
options != null ? options : UpsertOptions.upsertOptions());
|
||||
return Mono.just(object).flatMap(support::encodeEntity)
|
||||
.flatMap(converted -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive()
|
||||
.upsert(converted.getId(), converted.export(), buildUpsertOptions(pArgs.getOptions(), converted))
|
||||
.flatMap(converted -> template.getCouchbaseClientFactory().withScope(pArgs.getScope())
|
||||
.getCollection(pArgs.getCollection()).reactive()
|
||||
.upsert(converted.getId(), converted.export(), buildUpsertOptions(pArgs.getOptions(), converted))
|
||||
.flatMap(result -> support.applyUpdatedId(object, converted.getId())
|
||||
.flatMap(updatedObject -> (Mono<T>) support.applyUpdatedCas(updatedObject, result.cas()))))
|
||||
.flatMap(updatedObject -> support.applyUpdatedCas(updatedObject, converted, result.cas()))))
|
||||
.onErrorMap(throwable -> {
|
||||
if (throwable instanceof RuntimeException) {
|
||||
return template.potentiallyConvertRuntimeException((RuntimeException) throwable);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
|
||||
|
||||
public interface TemplateSupport {
|
||||
|
||||
@@ -23,11 +24,13 @@ public interface TemplateSupport {
|
||||
|
||||
<T> T decodeEntity(String id, String source, long cas, Class<T> entityClass);
|
||||
|
||||
Object applyUpdatedCas(Object entity, long cas);
|
||||
<T> T applyUpdatedCas(T entity, CouchbaseDocument converted, long cas);
|
||||
|
||||
Object applyUpdatedId(Object entity, Object id);
|
||||
<T> T applyUpdatedId(T entity, Object id);
|
||||
|
||||
long getCas(Object entity);
|
||||
|
||||
String getJavaNameForEntity(Class<?> clazz);
|
||||
|
||||
void maybeEmitEvent(CouchbaseMappingEvent<?> event);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,29 +15,27 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.Document;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
|
||||
/**
|
||||
* Callback being invoked after a domain object is materialized from a {@link Document} when reading results.
|
||||
* Callback being invoked after a domain object is materialized from a {@link CouchbaseDocument} when reading results.
|
||||
*
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Mark Paluch
|
||||
* @author Michael Reiche
|
||||
* @see org.springframework.data.mapping.callback.EntityCallbacks
|
||||
* @since 3.0
|
||||
* @since 4.2
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AfterConvertCallback<T> extends EntityCallback<T> {
|
||||
|
||||
/**
|
||||
* Entity callback method invoked after a domain object is materialized from a {@link Document}. Can return either the
|
||||
* same or a modified instance of the domain object.
|
||||
* Entity callback method invoked after a domain object is materialized from a {@link CouchbaseDocument}. Can return
|
||||
* either the same or a modified instance of the domain object.
|
||||
*
|
||||
* @param entity the domain object (the result of the conversion).
|
||||
* @param document must not be {@literal null}.
|
||||
* @param collection name of the collection.
|
||||
* @return the domain object that is the result of reading it from the {@link Document}.
|
||||
* @return the domain object that is the result of reading it from the {@link CouchbaseDocument}.
|
||||
*/
|
||||
T onAfterConvert(T entity, Document document, String collection);
|
||||
T onAfterConvert(T entity, CouchbaseDocument document, String collection);
|
||||
}
|
||||
|
||||
@@ -15,24 +15,27 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* {@link EntityCallback} to populate auditing related fields on an entity about to be saved.
|
||||
*
|
||||
* @author Jorge Rodríguez Martín
|
||||
* @since 4.2
|
||||
*/
|
||||
public class AuditingEntityCallback implements BeforeConvertCallback<Object>, Ordered {
|
||||
public class AuditingEntityCallback implements BeforeConvertCallback<Object>, AfterConvertCallback<Object>, Ordered {
|
||||
|
||||
private final ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuditingEntityCallback.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AuditingEntityCallback} using the given {@link MappingContext} and {@link AuditingHandler}
|
||||
@@ -41,7 +44,6 @@ public class AuditingEntityCallback implements BeforeConvertCallback<Object>, Or
|
||||
* @param auditingHandlerFactory must not be {@literal null}.
|
||||
*/
|
||||
public AuditingEntityCallback(ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory) {
|
||||
|
||||
Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!");
|
||||
this.auditingHandlerFactory = auditingHandlerFactory;
|
||||
}
|
||||
@@ -52,7 +54,19 @@ public class AuditingEntityCallback implements BeforeConvertCallback<Object>, Or
|
||||
*/
|
||||
@Override
|
||||
public Object onBeforeConvert(Object entity, String collection) {
|
||||
return auditingHandlerFactory.getObject().markAudited(entity);
|
||||
//LOG.debug("onBeforeConvert " + entity);
|
||||
return entity; // markAudited called in AuditingEventListener.onApplicationEvent()
|
||||
// auditingHandlerFactory.getObject().markAudited(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.couchbase.core.mapping.event.AfterConvertCallback#onAfterConvert(java.lang.Object, CouchbaseDocument, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object onAfterConvert(Object entity, CouchbaseDocument document, String collection) {
|
||||
//LOG.debug("onAfterConvert " + document);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,5 +78,4 @@ public class AuditingEntityCallback implements BeforeConvertCallback<Object>, Or
|
||||
return 100;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
@@ -33,7 +35,7 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Paluch
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class AuditingEventListener implements ApplicationListener<BeforeConvertEvent<Object>> {
|
||||
public class AuditingEventListener implements ApplicationListener<CouchbaseMappingEvent<Object>> {
|
||||
|
||||
private final ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory;
|
||||
|
||||
@@ -41,9 +43,11 @@ public class AuditingEventListener implements ApplicationListener<BeforeConvertE
|
||||
this.auditingHandlerFactory = null;
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuditingEventListener.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AuditingEventListener} using the given {@link MappingContext} and {@link AuditingHandler}
|
||||
* provided by the given {@link ObjectFactory}.
|
||||
* provided by the given {@link ObjectFactory}. Registered in CouchbaseAuditingRegistrar
|
||||
*
|
||||
* @param auditingHandlerFactory must not be {@literal null}.
|
||||
*/
|
||||
@@ -57,8 +61,29 @@ public class AuditingEventListener implements ApplicationListener<BeforeConvertE
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(BeforeConvertEvent<Object> event) {
|
||||
Optional.ofNullable(event.getSource())//
|
||||
.ifPresent(it -> auditingHandlerFactory.getObject().markAudited(it));
|
||||
public void onApplicationEvent(CouchbaseMappingEvent<Object> event) {
|
||||
if (event instanceof BeforeConvertEvent) {
|
||||
Optional.ofNullable(event.getSource())//
|
||||
.ifPresent(it -> auditingHandlerFactory.getObject().markAudited(it));
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof BeforeSaveEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof AfterSaveEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof BeforeDeleteEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof AfterDeleteEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (!event.getClass().getSimpleName().startsWith("Reactive")) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(event.getClass().getSimpleName() + " " + event.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveAfterDeleteEvent<E> extends CouchbaseMappingEvent<E> {
|
||||
|
||||
public ReactiveAfterDeleteEvent(E source) {
|
||||
super(source, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveAfterSaveEvent<E> extends CouchbaseMappingEvent<E> {
|
||||
|
||||
public ReactiveAfterSaveEvent(E source, CouchbaseDocument document) {
|
||||
super(source, document);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,27 +15,33 @@
|
||||
*/
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.Document;
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Reactive {@link EntityCallback} to populate auditing related fields on an entity about to be
|
||||
* saved. Based on <a href="https://github.com/spring-projects/spring-data-mongodb/blob/3.1.6/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java">ReactiveAfterConvertCallback</a>
|
||||
* Reactive {@link EntityCallback} to populate auditing related fields on an entity about to be saved. Based on <a href=
|
||||
* "https://github.com/spring-projects/spring-data-mongodb/blob/3.1.6/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/ReactiveAfterConvertCallback.java">ReactiveAfterConvertCallback</a>
|
||||
*
|
||||
* @author Jorge Rodríguez Martín
|
||||
* @authoer Michael Reiche
|
||||
* @since 4.2
|
||||
*/
|
||||
public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCallback<Object>, Ordered {
|
||||
public class ReactiveAuditingEntityCallback
|
||||
implements ReactiveBeforeConvertCallback<Object>, ReactiveAfterConvertCallback<Object>, Ordered {
|
||||
|
||||
private final ObjectFactory<ReactiveIsNewAwareAuditingHandler> auditingHandlerFactory;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ReactiveAuditingEntityCallback.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReactiveAuditingEntityCallback} using the given {@link MappingContext} and
|
||||
@@ -44,7 +50,7 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall
|
||||
* @param auditingHandlerFactory must not be {@literal null}.
|
||||
*/
|
||||
public ReactiveAuditingEntityCallback(final ObjectFactory<ReactiveIsNewAwareAuditingHandler> auditingHandlerFactory) {
|
||||
Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!");
|
||||
Assert.notNull(auditingHandlerFactory, "ReactiveIsNewAwareAuditingHandler must not be null!");
|
||||
this.auditingHandlerFactory = auditingHandlerFactory;
|
||||
}
|
||||
|
||||
@@ -57,9 +63,22 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall
|
||||
*/
|
||||
@Override
|
||||
public Publisher<Object> onBeforeConvert(final Object entity, final String collection) {
|
||||
LOG.debug("onBeforeConvert " + entity.toString());
|
||||
return this.auditingHandlerFactory.getObject().markAudited(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.couchbase.core.mapping.event.ReactiveAfterConvertCallback#onAfterConvert
|
||||
* (java.lang.Object, CouchbaseDocument, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Publisher<Object> onAfterConvert(Object entity, CouchbaseDocument document, String collection) {
|
||||
LOG.debug("onAfterConvert " + document.toString());
|
||||
return Mono.just(entity);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Reactive Event listener to populate auditing related fields on an entity about to be saved.
|
||||
*
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveAuditingEventListener implements ApplicationListener<CouchbaseMappingEvent<Object>> {
|
||||
|
||||
private final ObjectFactory<ReactiveIsNewAwareAuditingHandler> auditingHandlerFactory;
|
||||
|
||||
public ReactiveAuditingEventListener() {
|
||||
this.auditingHandlerFactory = null;
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ReactiveAuditingEventListener.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link ReactiveAuditingEventListener} using the given {@link MappingContext} and
|
||||
* {@link AuditingHandler} provided by the given {@link ObjectFactory}. Registered in CouchbaseAuditingRegistrar
|
||||
*
|
||||
* @param auditingHandlerFactory must not be {@literal null}.
|
||||
*/
|
||||
public ReactiveAuditingEventListener(ObjectFactory<ReactiveIsNewAwareAuditingHandler> auditingHandlerFactory) {
|
||||
Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!");
|
||||
this.auditingHandlerFactory = auditingHandlerFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(CouchbaseMappingEvent<Object> event) {
|
||||
if (event instanceof ReactiveBeforeConvertEvent) {
|
||||
Optional.ofNullable(event.getSource())//
|
||||
.ifPresent(it -> auditingHandlerFactory.getObject().markAudited(it));
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof ReactiveBeforeSaveEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof ReactiveAfterSaveEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof ReactiveBeforeDeleteEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event instanceof ReactiveAfterDeleteEvent) {
|
||||
// LOG.info(event.getClass().getSimpleName() + " " + event);
|
||||
}
|
||||
if (event.getClass().getSimpleName().startsWith("Reactive")) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(event.getClass().getSimpleName() + " " + event.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveBeforeConvertEvent<E> extends CouchbaseMappingEvent<E> {
|
||||
|
||||
public ReactiveBeforeConvertEvent(E source) {
|
||||
super(source, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveBeforeDeleteEvent<E> extends CouchbaseMappingEvent<E> {
|
||||
|
||||
public ReactiveBeforeDeleteEvent(E source) {
|
||||
super(source, null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
|
||||
/**
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
public class ReactiveBeforeSaveEvent<E> extends CouchbaseMappingEvent<E> {
|
||||
|
||||
public ReactiveBeforeSaveEvent(E source, CouchbaseDocument document) {
|
||||
super(source, document);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -80,13 +80,26 @@ public class CouchbaseAuditingRegistrar extends AuditingBeanDefinitionRegistrarS
|
||||
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!");
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
|
||||
|
||||
// Register the AuditEntityCallback
|
||||
|
||||
BeanDefinitionBuilder listenerBeanDefinitionBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AuditingEventListener.class);
|
||||
.rootBeanDefinition(AuditingEntityCallback.class);
|
||||
listenerBeanDefinitionBuilder
|
||||
.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
|
||||
registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(),
|
||||
AuditingEntityCallback.class.getName(), registry);
|
||||
|
||||
// Register the AuditingEventListener
|
||||
|
||||
BeanDefinitionBuilder listenerBeanDefinitionBuilder2 = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AuditingEventListener.class);
|
||||
listenerBeanDefinitionBuilder2
|
||||
.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
|
||||
registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder2.getBeanDefinition(),
|
||||
AuditingEventListener.class.getName(), registry);
|
||||
|
||||
}
|
||||
|
||||
private void ensureMappingContext(BeanDefinitionRegistry registry, Object source) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package org.springframework.data.couchbase.repository.auditing;
|
||||
|
||||
import static org.springframework.data.couchbase.config.BeanNames.*;
|
||||
import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_AUDITING_HANDLER;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -12,14 +13,16 @@ import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarS
|
||||
import org.springframework.data.auditing.config.AuditingConfiguration;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveAuditingEntityCallback;
|
||||
import org.springframework.data.couchbase.core.mapping.event.ReactiveAuditingEventListener;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* A support registrar that allows to set up reactive auditing for Couchbase (including {@link org.springframework.data.auditing.ReactiveAuditingHandler} and {
|
||||
* IsNewStrategyFactory} set up). See {@link EnableReactiveCouchbaseAuditing} for the associated annotation.
|
||||
* A support registrar that allows to set up reactive auditing for Couchbase (including
|
||||
* {@link org.springframework.data.auditing.ReactiveAuditingHandler} and { IsNewStrategyFactory} set up). See
|
||||
* {@link EnableReactiveCouchbaseAuditing} for the associated annotation.
|
||||
*
|
||||
* @author Jorge Rodríguez Martín
|
||||
* @author Michael Reiche
|
||||
* @since 4.2
|
||||
*/
|
||||
class ReactiveCouchbaseAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
||||
@@ -69,13 +72,27 @@ class ReactiveCouchbaseAuditingRegistrar extends AuditingBeanDefinitionRegistrar
|
||||
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!");
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
|
||||
|
||||
// Register the AuditingEntityCallback
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class);
|
||||
|
||||
builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
builder.getRawBeanDefinition().setSource(auditingHandlerDefinition.getSource());
|
||||
|
||||
registerInfrastructureBeanWithId(builder.getBeanDefinition(),
|
||||
ReactiveAuditingEntityCallback.class.getName(), registry);
|
||||
registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(),
|
||||
registry);
|
||||
|
||||
// Register the AuditingEventListener
|
||||
|
||||
BeanDefinitionBuilder builder2 = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEventListener.class);
|
||||
|
||||
builder2
|
||||
.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
builder.getRawBeanDefinition().setSource(auditingHandlerDefinition.getSource());
|
||||
|
||||
registerInfrastructureBeanWithId(builder2.getBeanDefinition(), ReactiveAuditingEventListener.class.getName(),
|
||||
registry);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
assertEquals(user, found);
|
||||
|
||||
couchbaseTemplate.removeById().one(user.getId());
|
||||
reactiveCouchbaseTemplate.replaceById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.THREE).one(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -280,9 +279,7 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
User user = new User(id, "firstname", "lastname");
|
||||
User inserted = couchbaseTemplate.insertById(User.class).one(user);
|
||||
assertEquals(user, inserted);
|
||||
|
||||
assertTrue(couchbaseTemplate.existsById().one(id));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.couchbase.core.ExecutableRemoveByIdOperation.ExecutableRemoveById;
|
||||
import org.springframework.data.couchbase.core.support.OneAndAllEntityReactive;
|
||||
import org.springframework.data.couchbase.domain.PersonValue;
|
||||
import org.springframework.data.couchbase.domain.User;
|
||||
import org.springframework.data.couchbase.domain.UserAnnotated;
|
||||
import org.springframework.data.couchbase.domain.UserAnnotated2;
|
||||
import org.springframework.data.couchbase.domain.UserAnnotated3;
|
||||
import org.springframework.data.couchbase.util.ClusterType;
|
||||
import org.springframework.data.couchbase.util.IgnoreWhen;
|
||||
import org.springframework.data.couchbase.util.JavaIntegrationTests;
|
||||
|
||||
import com.couchbase.client.java.kv.PersistTo;
|
||||
import com.couchbase.client.java.kv.ReplicateTo;
|
||||
|
||||
/**
|
||||
* KV tests Theses tests rely on a cb server running.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
|
||||
class ReactiveCouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests {
|
||||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void beforeEach() {
|
||||
super.beforeEach();
|
||||
reactiveCouchbaseTemplate.removeByQuery(User.class).all();
|
||||
reactiveCouchbaseTemplate.removeByQuery(UserAnnotated.class).all();
|
||||
reactiveCouchbaseTemplate.removeByQuery(UserAnnotated2.class).all();
|
||||
}
|
||||
|
||||
@Test
|
||||
void upsertAndFindById() {
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User modified = reactiveCouchbaseTemplate.upsertById(User.class).one(user).block();
|
||||
assertEquals(user, modified);
|
||||
|
||||
modified = reactiveCouchbaseTemplate.replaceById(User.class).one(user).block();
|
||||
assertEquals(user, modified);
|
||||
|
||||
user.setVersion(12345678);
|
||||
assertThrows(DataIntegrityViolationException.class,
|
||||
() -> reactiveCouchbaseTemplate.replaceById(User.class).one(user).block());
|
||||
|
||||
User found = reactiveCouchbaseTemplate.findById(User.class).one(user.getId()).block();
|
||||
user.setVersion(found.getVersion());
|
||||
assertEquals(user, found);
|
||||
|
||||
reactiveCouchbaseTemplate.removeById().one(user.getId()).block();
|
||||
}
|
||||
|
||||
@Test
|
||||
void withDurability()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
Class<?> clazz = User.class; // for now, just User.class. There is no Durability annotation.
|
||||
// insert, replace, upsert
|
||||
for (OneAndAllEntityReactive<User> operator : new OneAndAllEntityReactive[] {
|
||||
reactiveCouchbaseTemplate.insertById(clazz), reactiveCouchbaseTemplate.replaceById(clazz),
|
||||
reactiveCouchbaseTemplate.upsertById(clazz) }) {
|
||||
// create an entity of type clazz
|
||||
Constructor<?> cons = clazz.getConstructor(String.class, String.class, String.class);
|
||||
User user = (User) cons.newInstance("" + operator.getClass().getSimpleName() + "_" + clazz.getSimpleName(),
|
||||
"firstname", "lastname");
|
||||
|
||||
if (clazz.equals(User.class)) { // User.java doesn't have an durability annotation
|
||||
operator = (OneAndAllEntityReactive<User>) ((WithDurability<User>) operator).withDurability(PersistTo.ACTIVE,
|
||||
ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
// if replace, we need to insert a document to replace
|
||||
if (operator instanceof ReactiveReplaceByIdOperation.ReactiveReplaceById) {
|
||||
reactiveCouchbaseTemplate.insertById(User.class).one(user).block();
|
||||
}
|
||||
// call to insert/replace/update
|
||||
User returned = operator.one(user).block();
|
||||
assertEquals(user, returned);
|
||||
User found = reactiveCouchbaseTemplate.findById(User.class).one(user.getId()).block();
|
||||
assertEquals(user, found);
|
||||
|
||||
if (operator instanceof ReactiveReplaceByIdOperation.ReactiveReplaceById) {
|
||||
reactiveCouchbaseTemplate.removeById().withDurability(PersistTo.ACTIVE, ReplicateTo.NONE).one(user.getId())
|
||||
.block();
|
||||
User removed = (User) reactiveCouchbaseTemplate.findById(user.getClass()).one(user.getId()).block();
|
||||
assertNull(removed, "found should have been null as document should be removed");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void withExpiryAndExpiryAnnotation()
|
||||
throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
||||
// ( withExpiry()<User>, expiry=1<UserAnnotated>, expiryExpression=${myExpiry}<UserAnnotated2> ) X ( insert,
|
||||
// replace, upsert )
|
||||
Set<User> users = new HashSet<>(); // set of all documents we will insert
|
||||
// Entity classes
|
||||
for (Class<?> clazz : new Class[] { User.class, UserAnnotated.class, UserAnnotated2.class, UserAnnotated3.class }) {
|
||||
// insert, replace, upsert
|
||||
for (OneAndAllEntityReactive<User> operator : new OneAndAllEntityReactive[] {
|
||||
reactiveCouchbaseTemplate.insertById(clazz), reactiveCouchbaseTemplate.replaceById(clazz),
|
||||
reactiveCouchbaseTemplate.upsertById(clazz) }) {
|
||||
|
||||
// create an entity of type clazz
|
||||
Constructor<?> cons = clazz.getConstructor(String.class, String.class, String.class);
|
||||
User user = (User) cons.newInstance("" + operator.getClass().getSimpleName() + "_" + clazz.getSimpleName(),
|
||||
"firstname", "lastname");
|
||||
|
||||
if (clazz.equals(User.class)) { // User.java doesn't have an expiry annotation
|
||||
operator = (OneAndAllEntityReactive<User>) ((WithExpiry<User>) operator).withExpiry(Duration.ofSeconds(1));
|
||||
} else if (clazz.equals(UserAnnotated3.class)) { // override the expiry from the annotation with no expiry
|
||||
operator = (OneAndAllEntityReactive<User>) ((WithExpiry<User>) operator).withExpiry(Duration.ofSeconds(0));
|
||||
}
|
||||
|
||||
// if replace or remove, we need to insert a document to replace
|
||||
if (operator instanceof ReactiveReplaceByIdOperation.ReactiveReplaceById || operator instanceof ExecutableRemoveById) {
|
||||
reactiveCouchbaseTemplate.insertById(User.class).one(user).block();
|
||||
}
|
||||
// call to insert/replace/update
|
||||
User returned = operator.one(user).block();
|
||||
assertEquals(user, returned);
|
||||
users.add(user);
|
||||
}
|
||||
}
|
||||
// check that they are gone after a few seconds.
|
||||
sleepSecs(4);
|
||||
for (User user : users) {
|
||||
User found = reactiveCouchbaseTemplate.findById(user.getClass()).one(user.getId()).block();
|
||||
if (found instanceof UserAnnotated3) {
|
||||
assertNotNull(found, "found should be non null as it was set to have no expirty");
|
||||
} else {
|
||||
assertNull(found, "found should have been null as document should be expired");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void findDocWhichDoesNotExist() {
|
||||
assertNull(reactiveCouchbaseTemplate.findById(User.class).one(UUID.randomUUID().toString()).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void upsertAndReplaceById() {
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User modified = reactiveCouchbaseTemplate.upsertById(User.class).one(user).block();
|
||||
assertEquals(user, modified);
|
||||
|
||||
User toReplace = new User(modified.getId(), "some other", "lastname");
|
||||
reactiveCouchbaseTemplate.replaceById(User.class).one(toReplace).block();
|
||||
|
||||
User loaded = reactiveCouchbaseTemplate.findById(User.class).one(toReplace.getId()).block();
|
||||
assertEquals("some other", loaded.getFirstname());
|
||||
|
||||
reactiveCouchbaseTemplate.removeById().one(toReplace.getId()).block();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void upsertAndRemoveById() {
|
||||
{
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User modified = reactiveCouchbaseTemplate.upsertById(User.class).one(user).block();
|
||||
assertEquals(user, modified);
|
||||
|
||||
RemoveResult removeResult = reactiveCouchbaseTemplate.removeById().one(user.getId()).block();
|
||||
assertEquals(user.getId(), removeResult.getId());
|
||||
assertTrue(removeResult.getCas() != 0);
|
||||
assertTrue(removeResult.getMutationToken().isPresent());
|
||||
|
||||
assertNull(reactiveCouchbaseTemplate.findById(User.class).one(user.getId()).block());
|
||||
}
|
||||
{
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User modified = reactiveCouchbaseTemplate.upsertById(User.class).one(user).block();
|
||||
assertEquals(user, modified);
|
||||
|
||||
// careful now - user and modified are the same object. The object has the new cas (@Version version)
|
||||
Long savedCas = modified.getVersion();
|
||||
modified.setVersion(123);
|
||||
assertThrows(DataIntegrityViolationException.class, () -> reactiveCouchbaseTemplate.removeById()
|
||||
.withCas(reactiveCouchbaseTemplate.support().getCas(modified)).one(modified.getId()).block());
|
||||
modified.setVersion(savedCas);
|
||||
reactiveCouchbaseTemplate.removeById().withCas(reactiveCouchbaseTemplate.support().getCas(modified))
|
||||
.one(modified.getId()).block();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void insertById() {
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User inserted = reactiveCouchbaseTemplate.insertById(User.class).one(user).block();
|
||||
assertEquals(user, inserted);
|
||||
assertThrows(DuplicateKeyException.class, () -> reactiveCouchbaseTemplate.insertById(User.class).one(user).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void insertByIdwithDurability() {
|
||||
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
|
||||
User inserted = reactiveCouchbaseTemplate.insertById(User.class).withDurability(PersistTo.ACTIVE, ReplicateTo.NONE)
|
||||
.one(user).block();
|
||||
assertEquals(user, inserted);
|
||||
assertThrows(DuplicateKeyException.class, () -> reactiveCouchbaseTemplate.insertById(User.class).one(user).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void existsById() {
|
||||
String id = UUID.randomUUID().toString();
|
||||
assertFalse(reactiveCouchbaseTemplate.existsById().one(id).block());
|
||||
|
||||
User user = new User(id, "firstname", "lastname");
|
||||
User inserted = reactiveCouchbaseTemplate.insertById(User.class).one(user).block();
|
||||
assertEquals(user, inserted);
|
||||
|
||||
assertTrue(reactiveCouchbaseTemplate.existsById().one(id).block());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
|
||||
void saveAndFindImmutableById() {
|
||||
PersonValue personValue = new PersonValue(UUID.randomUUID().toString(), 123, "f", "l");
|
||||
PersonValue inserted;
|
||||
PersonValue upserted;
|
||||
PersonValue replaced;
|
||||
|
||||
inserted = reactiveCouchbaseTemplate.insertById(PersonValue.class).one(personValue).block();
|
||||
assertNotEquals(0, inserted.getVersion());
|
||||
PersonValue foundInserted = reactiveCouchbaseTemplate.findById(PersonValue.class).one(inserted.getId()).block();
|
||||
assertNotNull(foundInserted, "inserted personValue not found");
|
||||
assertEquals(inserted, foundInserted);
|
||||
|
||||
// upsert will insert
|
||||
reactiveCouchbaseTemplate.removeById().one(inserted.getId());
|
||||
upserted = reactiveCouchbaseTemplate.upsertById(PersonValue.class).one(inserted).block();
|
||||
assertNotEquals(0, upserted.getVersion());
|
||||
PersonValue foundUpserted = reactiveCouchbaseTemplate.findById(PersonValue.class).one(upserted.getId()).block();
|
||||
assertNotNull(foundUpserted, "upserted personValue not found");
|
||||
assertEquals(upserted, foundUpserted);
|
||||
|
||||
// upsert will replace
|
||||
upserted = reactiveCouchbaseTemplate.upsertById(PersonValue.class).one(inserted).block();
|
||||
assertNotEquals(0, upserted.getVersion());
|
||||
PersonValue foundUpserted2 = reactiveCouchbaseTemplate.findById(PersonValue.class).one(upserted.getId()).block();
|
||||
assertNotNull(foundUpserted2, "upserted personValue not found");
|
||||
assertEquals(upserted, foundUpserted2);
|
||||
|
||||
replaced = reactiveCouchbaseTemplate.replaceById(PersonValue.class).one(upserted).block();
|
||||
assertNotEquals(0, replaced.getVersion());
|
||||
PersonValue foundReplaced = reactiveCouchbaseTemplate.findById(PersonValue.class).one(replaced.getId()).block();
|
||||
assertNotNull(foundReplaced, "replaced personValue not found");
|
||||
assertEquals(replaced, foundReplaced);
|
||||
|
||||
}
|
||||
|
||||
private void sleepSecs(int i) {
|
||||
try {
|
||||
Thread.sleep(i * 1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,11 +52,8 @@ import com.couchbase.client.java.json.JacksonTransformers;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCouchbaseRepositories
|
||||
@EnableCouchbaseAuditing(auditorAwareRef = "auditorAwareRef", dateTimeProviderRef = "dateTimeProviderRef") // this
|
||||
// activates
|
||||
// auditing
|
||||
@EnableReactiveCouchbaseAuditing(auditorAwareRef = "reactiveAuditorAwareRef",
|
||||
dateTimeProviderRef = "dateTimeProviderRef") // this activates auditing
|
||||
@EnableCouchbaseAuditing(auditorAwareRef="auditorAwareRef", dateTimeProviderRef="dateTimeProviderRef") // this activates auditing
|
||||
@EnableReactiveCouchbaseAuditing(auditorAwareRef="reactiveAuditorAwareRef", dateTimeProviderRef="dateTimeProviderRef") // this activates auditing
|
||||
|
||||
public class Config extends AbstractCouchbaseConfiguration {
|
||||
String bucketname = "travel-sample";
|
||||
|
||||
@@ -32,7 +32,8 @@ import org.springframework.data.domain.AuditorAware;
|
||||
*/
|
||||
public class NaiveAuditorAware implements AuditorAware<String> {
|
||||
|
||||
private Optional<String> auditor = Optional.of("auditor");
|
||||
static public final String AUDITOR = "auditor";
|
||||
private Optional<String> auditor = Optional.of(AUDITOR);
|
||||
|
||||
@Override
|
||||
public Optional<String> getCurrentAuditor() {
|
||||
|
||||
@@ -27,9 +27,10 @@ import reactor.core.publisher.Mono;
|
||||
*/
|
||||
public class ReactiveNaiveAuditorAware implements ReactiveAuditorAware<String> {
|
||||
|
||||
public static final String AUDITOR = "reactive_auditor";
|
||||
@Override
|
||||
public Mono<String> getCurrentAuditor() {
|
||||
return Mono.just("auditor");
|
||||
return Mono.just(AUDITOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr
|
||||
Airport saved = airportRepository.save(vie);
|
||||
List<Airport> airports1 = airportRepository.findAllByIata("vie");
|
||||
assertEquals(saved, airports1.get(0));
|
||||
assertEquals(saved.getCreatedBy(), "auditor"); // NaiveAuditorAware will provide this
|
||||
assertEquals(saved.getCreatedBy(), NaiveAuditorAware.AUDITOR); // NaiveAuditorAware will provide this
|
||||
} finally {
|
||||
airportRepository.delete(vie);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ReactiveCouchbaseRepositoryKeyValueIntegrationTests extends Cluster
|
||||
Airport saved = airportRepository.save(vie).block();
|
||||
Airport airport1 = airportRepository.findById(saved.getId()).block();
|
||||
assertEquals(airport1, saved);
|
||||
assertEquals(saved.getCreatedBy(), "auditor"); // NaiveAuditorAware will provide this
|
||||
assertEquals(saved.getCreatedBy(), ReactiveNaiveAuditorAware.AUDITOR); // ReactiveNaiveAuditorAware will provide this
|
||||
} finally {
|
||||
airportRepository.delete(vie).block();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user