Skip to content

Add missing hooks for callbacks. #1142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
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;
Expand Down Expand Up @@ -95,16 +96,21 @@ public <T> T decodeEntity(String id, String source, long cas, Class<T> entityCla
}

@Override
public Object applyUpdatedCas(final Object entity, final long cas) {
public Object applyUpdatedCas(final Object entity, CouchbaseDocument converted, final long cas) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added converted CouchbaseDocument to args as AfterSaveEvent takes a CouchbaseDocument.

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
Expand Down Expand Up @@ -172,7 +178,7 @@ public void setEntityCallbacks(EntityCallbacks entityCallbacks) {
this.entityCallbacks = entityCallbacks;
}

void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
if (canPublishEvent()) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to call from ReactiveRemoveByIdOperationSupport

try {
this.applicationContext.publishEvent(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;

import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEvent;
import reactor.core.publisher.Mono;

/**
Expand Down Expand Up @@ -44,8 +45,8 @@ public <T> Mono<T> decodeEntity(String id, String source, long cas, Class<T> ent
}

@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
Expand All @@ -62,4 +63,9 @@ public Long getCas(Object entity) {
public String getJavaNameForEntity(Class<?> clazz) {
return support.getJavaNameForEntity(clazz);
}

@Override
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
support.maybeEmitEvent(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,19 +30,18 @@
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;
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}.
Expand All @@ -65,16 +68,13 @@ public ReactiveCouchbaseTemplateSupport(final CouchbaseConverter converter,

@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
Expand All @@ -98,25 +98,31 @@ public <T> Mono<T> decodeEntity(String id, String source, long cas, Class<T> ent
}

@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;
});
}

@Override
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) {
Expand All @@ -130,8 +136,7 @@ public Mono<Object> applyUpdatedId(final Object entity, Object id) {
@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;
Expand Down Expand Up @@ -166,9 +171,9 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
}

/**
* 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}.
*
Expand All @@ -180,7 +185,7 @@ public void setReactiveEntityCallbacks(ReactiveEntityCallbacks reactiveEntityCal
this.reactiveEntityCallbacks = reactiveEntityCallbacks;
}

void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
public void maybeEmitEvent(CouchbaseMappingEvent<?> event) {
if (canPublishEvent()) {
try {
this.applicationContext.publishEvent(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,16 @@ static class ReactiveInsertByIdSupport<T> implements ReactiveInsertById<T> {

@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -68,19 +70,22 @@ static class ReactiveRemoveByIdSupport implements ReactiveRemoveById {

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ static class ReactiveReplaceByIdSupport<T> implements ReactiveReplaceById<T> {

@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

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 {
Expand All @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ static class ReactiveUpsertByIdSupport<T> implements ReactiveUpsertById<T> {

@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@
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 {

CouchbaseDocument encodeEntity(Object entityToEncode);

<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);
}
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was copied incorrectly from Mongo with the second arg of Document instead of CouchbaseDocument.

}
Loading