From 7501c19be46f3b2d7e3e7dfa9edbf43e86c4eeff Mon Sep 17 00:00:00 2001 From: Roman Puchkovskiy Date: Tue, 21 Apr 2020 23:24:22 +0400 Subject: [PATCH] DATAES-785 - Various entity callbacks implementation improvements. Original PR: #431 --- .../core/AbstractElasticsearchTemplate.java | 24 +- .../core/ElasticsearchRestTemplate.java | 8 +- .../core/ElasticsearchTemplate.java | 8 +- .../core/ReactiveElasticsearchTemplate.java | 109 +++++--- .../core/event/AfterSaveCallback.java | 4 +- .../core/event/AuditingEntityCallback.java | 4 +- .../core/event/BeforeConvertCallback.java | 5 +- .../core/event/ReactiveAfterSaveCallback.java | 4 +- .../event/ReactiveAuditingEntityCallback.java | 4 +- .../event/ReactiveBeforeConvertCallback.java | 5 +- .../config/AuditingIntegrationTest.java | 6 +- .../ReactiveAuditingIntegrationTest.java | 6 +- ...actElasticsearchTemplateCallbackTests.java | 249 +++++++++++++----- ...iveElasticsearchTemplateCallbackTests.java | 188 +++++++------ .../event/AuditingEntityCallbackTests.java | 6 +- .../ElasticsearchOperationsCallbackTest.java | 4 +- .../ReactiveAuditingEntityCallbackTests.java | 6 +- ...veElasticsearchOperationsCallbackTest.java | 4 +- 18 files changed, 413 insertions(+), 231 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java index 3f4a96e14..0fa786821 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java @@ -463,23 +463,23 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper // endregion // region Entity callbacks - protected T maybeCallbackBeforeConvert(T entity) { + protected T maybeCallbackBeforeConvert(T entity, IndexCoordinates index) { if (entityCallbacks != null) { - return entityCallbacks.callback(BeforeConvertCallback.class, entity); + return entityCallbacks.callback(BeforeConvertCallback.class, entity, index); } return entity; } - protected void maybeCallbackBeforeConvertWithQuery(Object query) { + protected void maybeCallbackBeforeConvertWithQuery(Object query, IndexCoordinates index) { if (query instanceof IndexQuery) { IndexQuery indexQuery = (IndexQuery) query; Object queryObject = indexQuery.getObject(); if (queryObject != null) { - queryObject = maybeCallbackBeforeConvert(queryObject); + queryObject = maybeCallbackBeforeConvert(queryObject, index); indexQuery.setObject(queryObject); } } @@ -487,27 +487,27 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper // this can be called with either a List or a List; these query classes // don't have a common base class, therefore the List argument - protected void maybeCallbackBeforeConvertWithQueries(List queries) { - queries.forEach(this::maybeCallbackBeforeConvertWithQuery); + protected void maybeCallbackBeforeConvertWithQueries(List queries, IndexCoordinates index) { + queries.forEach(query -> maybeCallbackBeforeConvertWithQuery(query, index)); } - protected T maybeCallbackAfterSave(T entity) { + protected T maybeCallbackAfterSave(T entity, IndexCoordinates index) { if (entityCallbacks != null) { - return entityCallbacks.callback(AfterSaveCallback.class, entity); + return entityCallbacks.callback(AfterSaveCallback.class, entity, index); } return entity; } - protected void maybeCallbackAfterSaveWithQuery(Object query) { + protected void maybeCallbackAfterSaveWithQuery(Object query, IndexCoordinates index) { if (query instanceof IndexQuery) { IndexQuery indexQuery = (IndexQuery) query; Object queryObject = indexQuery.getObject(); if (queryObject != null) { - queryObject = maybeCallbackAfterSave(queryObject); + queryObject = maybeCallbackAfterSave(queryObject, index); indexQuery.setObject(queryObject); } } @@ -515,8 +515,8 @@ public abstract class AbstractElasticsearchTemplate implements ElasticsearchOper // this can be called with either a List or a List; these query classes // don't have a common base class, therefore the List argument - protected void maybeCallbackAfterSaveWithQueries(List queries) { - queries.forEach(this::maybeCallbackAfterSaveWithQuery); + protected void maybeCallbackAfterSaveWithQueries(List queries, IndexCoordinates index) { + queries.forEach(query -> maybeCallbackAfterSaveWithQuery(query, index)); } protected T maybeCallbackAfterConvert(T entity, Document document, IndexCoordinates index) { diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java index 308aaed3b..3d6fc25c5 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java @@ -136,7 +136,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { @Override public String index(IndexQuery query, IndexCoordinates index) { - maybeCallbackBeforeConvertWithQuery(query); + maybeCallbackBeforeConvertWithQuery(query, index); IndexRequest request = requestFactory.indexRequest(query, index); String documentId = execute(client -> client.index(request, RequestOptions.DEFAULT).getId()); @@ -147,7 +147,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { setPersistentEntityId(queryObject, documentId); } - maybeCallbackAfterSaveWithQuery(query); + maybeCallbackAfterSaveWithQuery(query, index); return documentId; } @@ -232,11 +232,11 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate { } private List doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { - maybeCallbackBeforeConvertWithQueries(queries); + maybeCallbackBeforeConvertWithQueries(queries, index); BulkRequest bulkRequest = requestFactory.bulkRequest(queries, bulkOptions, index); List ids = checkForBulkOperationFailure( execute(client -> client.bulk(bulkRequest, RequestOptions.DEFAULT))); - maybeCallbackAfterSaveWithQueries(queries); + maybeCallbackAfterSaveWithQueries(queries, index); return ids; } // endregion diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 467e1f585..43ca3b1c5 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -142,7 +142,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { @Override public String index(IndexQuery query, IndexCoordinates index) { - maybeCallbackBeforeConvertWithQuery(query); + maybeCallbackBeforeConvertWithQuery(query, index); IndexRequestBuilder indexRequestBuilder = requestFactory.indexRequestBuilder(client, query, index); String documentId = indexRequestBuilder.execute().actionGet().getId(); @@ -153,7 +153,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { setPersistentEntityId(queryObject, documentId); } - maybeCallbackAfterSaveWithQuery(query); + maybeCallbackAfterSaveWithQuery(query, index); return documentId; } @@ -196,7 +196,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { List ids = doBulkOperation(queries, bulkOptions, index); - maybeCallbackAfterSaveWithQueries(queries); + maybeCallbackAfterSaveWithQueries(queries, index); return ids; } @@ -245,7 +245,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate { } private List doBulkOperation(List queries, BulkOptions bulkOptions, IndexCoordinates index) { - maybeCallbackBeforeConvertWithQueries(queries); + maybeCallbackBeforeConvertWithQueries(queries, index); BulkRequestBuilder bulkRequest = requestFactory.bulkRequestBuilder(client, queries, bulkOptions, index); return checkForBulkOperationFailure(bulkRequest.execute().actionGet()); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java index c9f006b7c..b8054ea5c 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java @@ -19,12 +19,12 @@ import static org.elasticsearch.index.VersionType.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.util.function.Tuple2; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -187,12 +187,15 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera Assert.notNull(entity, "Entity must not be null!"); - AdaptibleEntity adaptableEntity = operations.forEntity(entity, converter.getConversionService()); - - return doIndex(entity, adaptableEntity, index) // + return maybeCallBeforeConvert(entity, index) + .flatMap(entityAfterBeforeConversionCallback -> doIndex(entityAfterBeforeConversionCallback, index)) // .map(it -> { - return adaptableEntity.populateIdIfNecessary(it.getId()); - }).flatMap(this::maybeCallAfterSave); + T savedEntity = it.getT1(); + IndexResponse indexResponse = it.getT2(); + AdaptibleEntity adaptableEntity = operations.forEntity(savedEntity, converter.getConversionService()); + return adaptableEntity.populateIdIfNecessary(indexResponse.getId()); + }) + .flatMap(saved -> maybeCallAfterSave(saved, index)); } @Override @@ -201,32 +204,35 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera } @Override - public Flux saveAll(Mono> entities, IndexCoordinates index) { + public Flux saveAll(Mono> entitiesPublisher, IndexCoordinates index) { - Assert.notNull(entities, "Entities must not be null!"); + Assert.notNull(entitiesPublisher, "Entities must not be null!"); - return entities.flatMapMany(entityList -> { + return entitiesPublisher + .flatMapMany(entities -> { + return Flux.fromIterable(entities) // + .concatMap(entity -> maybeCallBeforeConvert(entity, index)); + }) + .collectList() + .map(Entities::new) + .flatMapMany(entities -> { + if (entities.isEmpty()) { + return Flux.empty(); + } - List> adaptibleEntities = entityList.stream() // - .map(e -> operations.forEntity(e, converter.getConversionService())) // - .collect(Collectors.toList()); + return doBulkOperation(entities.indexQueries(), BulkOptions.defaultOptions(), index) // + .index() + .flatMap(indexAndResponse -> { + T savedEntity = entities.entityAt(indexAndResponse.getT1()); + BulkItemResponse bulkItemResponse = indexAndResponse.getT2(); - if (adaptibleEntities.isEmpty()) { - return Flux.empty(); - } + AdaptibleEntity adaptibleEntity = operations.forEntity(savedEntity, + converter.getConversionService()); + adaptibleEntity.populateIdIfNecessary(bulkItemResponse.getResponse().getId()); - Iterator> iterator = adaptibleEntities.iterator(); - List indexRequests = adaptibleEntities.stream() // - .map(e -> getIndexQuery(e.getBean(), e)) // - .collect(Collectors.toList()); - return doBulkOperation(indexRequests, BulkOptions.defaultOptions(), index) // - .flatMap(bulkItemResponse -> { - - AdaptibleEntity mappedEntity = iterator.next(); - mappedEntity.populateIdIfNecessary(bulkItemResponse.getResponse().getId()); - return maybeCallAfterSave(mappedEntity.getBean()); - }); - }); + return maybeCallAfterSave(savedEntity, index); + }); + }); } @Override @@ -332,13 +338,12 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera .onErrorReturn(NoSuchIndexException.class, false); } - private Mono doIndex(Object value, AdaptibleEntity entity, IndexCoordinates index) { + private Mono> doIndex(T entity, IndexCoordinates index) { - return maybeCallBeforeConvert(value).flatMap(it -> { - IndexRequest request = getIndexRequest(value, entity, index); - request = prepareIndexRequest(value, request); - return doIndex(request); - }); + AdaptibleEntity adaptibleEntity = operations.forEntity(entity, converter.getConversionService()); + IndexRequest request = getIndexRequest(entity, adaptibleEntity, index); + request = prepareIndexRequest(entity, request); + return Mono.just(entity).zipWith(doIndex(request)); } private IndexRequest getIndexRequest(Object value, AdaptibleEntity entity, IndexCoordinates index) { @@ -361,7 +366,9 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera return request; } - private IndexQuery getIndexQuery(Object value, AdaptibleEntity entity) { + private IndexQuery getIndexQuery(Object value) { + AdaptibleEntity entity = operations.forEntity(value, converter.getConversionService()); + Object id = entity.getId(); IndexQuery query = new IndexQuery(); if (id != null) { @@ -912,19 +919,19 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera } // region callbacks - protected Mono maybeCallBeforeConvert(T entity) { + protected Mono maybeCallBeforeConvert(T entity, IndexCoordinates index) { if (null != entityCallbacks) { - return entityCallbacks.callback(ReactiveBeforeConvertCallback.class, entity); + return entityCallbacks.callback(ReactiveBeforeConvertCallback.class, entity, index); } return Mono.just(entity); } - protected Mono maybeCallAfterSave(T entity) { + protected Mono maybeCallAfterSave(T entity, IndexCoordinates index) { if (null != entityCallbacks) { - return entityCallbacks.callback(ReactiveAfterSaveCallback.class, entity); + return entityCallbacks.callback(ReactiveAfterSaveCallback.class, entity, index); } return Mono.just(entity); @@ -995,4 +1002,30 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera .map(entity -> SearchHitMapping.mappingFor(type, converter.getMappingContext()).mapHit(response, entity)); } } + + private class Entities { + private final List entities; + + private Entities(List entities) { + Assert.notNull(entities, "entities cannot be null"); + + this.entities = entities; + } + + private boolean isEmpty() { + return entities.isEmpty(); + } + + private List indexQueries() { + return entities.stream() + .map(ReactiveElasticsearchTemplate.this::getIndexQuery) + .collect(Collectors.toList()); + } + + private T entityAt(long index) { + // it's safe to cast to int because the original indexed colleciton was fitting in memory + int intIndex = (int) index; + return entities.get(intIndex); + } + } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/AfterSaveCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/AfterSaveCallback.java index ca9639b8d..e67a354a6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/AfterSaveCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/AfterSaveCallback.java @@ -15,6 +15,7 @@ */ package org.springframework.data.elasticsearch.core.event; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.EntityCallbacks; @@ -33,7 +34,8 @@ public interface AfterSaveCallback extends EntityCallback { * the domain object. * * @param entity the domain object that was saved. + * @param index must not be {@literal null}. * @return the domain object that was persisted. */ - T onAfterSave(T entity); + T onAfterSave(T entity, IndexCoordinates index); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallback.java index 779b32ba5..a8e136dbf 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallback.java @@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core.event; import org.springframework.beans.factory.ObjectFactory; import org.springframework.core.Ordered; import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.util.Assert; @@ -25,6 +26,7 @@ import org.springframework.util.Assert; * {@link EntityCallback} to populate auditing related fields on an entity about to be saved. * * @author Peter-Josef Meisch + * @author Roman Puchkovskiy * @since 4.0 */ public class AuditingEntityCallback implements BeforeConvertCallback, Ordered { @@ -45,7 +47,7 @@ public class AuditingEntityCallback implements BeforeConvertCallback, Or } @Override - public Object onBeforeConvert(Object entity) { + public Object onBeforeConvert(Object entity, IndexCoordinates index) { return auditingHandlerFactory.getObject().markAudited(entity); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/BeforeConvertCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/BeforeConvertCallback.java index 85d50706f..f39703b19 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/BeforeConvertCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/BeforeConvertCallback.java @@ -15,12 +15,14 @@ */ package org.springframework.data.elasticsearch.core.event; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.callback.EntityCallback; /** * Callback being invoked before a domain object is converted to be persisted. * * @author Peter-Josef Meisch + * @author Roman Puchkovskiy * @since 4.0 */ @FunctionalInterface @@ -31,7 +33,8 @@ public interface BeforeConvertCallback extends EntityCallback { * the domain entity class. * * @param entity the entity being converted + * @param index must not be {@literal null}. * @return the entity to be converted */ - T onBeforeConvert(T entity); + T onBeforeConvert(T entity, IndexCoordinates index); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAfterSaveCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAfterSaveCallback.java index 032e41962..e6db4214b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAfterSaveCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAfterSaveCallback.java @@ -16,6 +16,7 @@ package org.springframework.data.elasticsearch.core.event; import org.reactivestreams.Publisher; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.callback.EntityCallback; import org.springframework.data.mapping.callback.ReactiveEntityCallbacks; @@ -34,7 +35,8 @@ public interface ReactiveAfterSaveCallback extends EntityCallback { * the domain object. * * @param entity the domain object that was saved. + * @param index must not be {@literal null}. * @return a {@link Publisher} emitting the domain object to be returned to the caller. */ - Publisher onAfterSave(T entity); + Publisher onAfterSave(T entity, IndexCoordinates index); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallback.java index 4051d5f71..68dedec4b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallback.java @@ -15,6 +15,7 @@ */ package org.springframework.data.elasticsearch.core.event; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import reactor.core.publisher.Mono; import org.springframework.beans.factory.ObjectFactory; @@ -27,6 +28,7 @@ import org.springframework.util.Assert; * {@link EntityCallback} to populate auditing related fields on an entity about to be saved. * * @author Peter-Josef Meisch + * @author Roman Puchkovskiy * @since 4.0 */ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCallback, Ordered { @@ -47,7 +49,7 @@ public class ReactiveAuditingEntityCallback implements ReactiveBeforeConvertCall } @Override - public Mono onBeforeConvert(Object entity) { + public Mono onBeforeConvert(Object entity, IndexCoordinates index) { return Mono.just(auditingHandlerFactory.getObject().markAudited(entity)); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveBeforeConvertCallback.java b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveBeforeConvertCallback.java index e09b3ed25..457a69521 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveBeforeConvertCallback.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/event/ReactiveBeforeConvertCallback.java @@ -16,12 +16,14 @@ package org.springframework.data.elasticsearch.core.event; import org.reactivestreams.Publisher; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.mapping.callback.EntityCallback; /** * Callback being invoked before a domain object is converted to be persisted. * * @author Peter-Josef Meisch + * @author Roman Puchkovskiy * @since 4.0 */ @FunctionalInterface @@ -32,7 +34,8 @@ public interface ReactiveBeforeConvertCallback extends EntityCallback { * the domain entity class. * * @param entity the entity being converted + * @param index must not be {@literal null}. * @return the entity to be converted */ - Publisher onBeforeConvert(T entity); + Publisher onBeforeConvert(T entity, IndexCoordinates index); } diff --git a/src/test/java/org/springframework/data/elasticsearch/config/AuditingIntegrationTest.java b/src/test/java/org/springframework/data/elasticsearch/config/AuditingIntegrationTest.java index 4c5f80d21..1d9736d47 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/AuditingIntegrationTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/AuditingIntegrationTest.java @@ -31,12 +31,14 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Persistable; import org.springframework.data.elasticsearch.core.event.BeforeConvertCallback; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.lang.Nullable; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ public abstract class AuditingIntegrationTest { @@ -64,7 +66,7 @@ public abstract class AuditingIntegrationTest { Entity entity = new Entity(); entity.setId("1"); - entity = callbacks.callback(BeforeConvertCallback.class, entity); + entity = callbacks.callback(BeforeConvertCallback.class, entity, IndexCoordinates.of("index")); assertThat(entity.getCreated()).isNotNull(); assertThat(entity.getModified()).isEqualTo(entity.created); @@ -73,7 +75,7 @@ public abstract class AuditingIntegrationTest { Thread.sleep(10); - entity = callbacks.callback(BeforeConvertCallback.class, entity); + entity = callbacks.callback(BeforeConvertCallback.class, entity, IndexCoordinates.of("index")); assertThat(entity.getCreated()).isNotNull(); assertThat(entity.getModified()).isNotEqualTo(entity.created); diff --git a/src/test/java/org/springframework/data/elasticsearch/config/ReactiveAuditingIntegrationTest.java b/src/test/java/org/springframework/data/elasticsearch/config/ReactiveAuditingIntegrationTest.java index a9bf3541c..29436c001 100644 --- a/src/test/java/org/springframework/data/elasticsearch/config/ReactiveAuditingIntegrationTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/config/ReactiveAuditingIntegrationTest.java @@ -33,6 +33,7 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Persistable; import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; @@ -42,6 +43,7 @@ import org.springframework.test.context.ContextConfiguration; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ @SpringIntegrationTest @ContextConfiguration(classes = { ReactiveAuditingIntegrationTest.Config.class }) @@ -81,7 +83,7 @@ public class ReactiveAuditingIntegrationTest { Entity entity = new Entity(); entity.setId("1"); - entity = callbacks.callback(ReactiveBeforeConvertCallback.class, entity).block(); + entity = callbacks.callback(ReactiveBeforeConvertCallback.class, entity, IndexCoordinates.of("index")).block(); assertThat(entity.getCreated()).isNotNull(); assertThat(entity.getModified()).isEqualTo(entity.created); @@ -90,7 +92,7 @@ public class ReactiveAuditingIntegrationTest { Thread.sleep(10); - entity = callbacks.callback(ReactiveBeforeConvertCallback.class, entity).block(); + entity = callbacks.callback(ReactiveBeforeConvertCallback.class, entity, IndexCoordinates.of("index")).block(); assertThat(entity.getCreated()).isNotNull(); assertThat(entity.getModified()).isNotEqualTo(entity.created); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java index 8f732fe84..34c6dc107 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java @@ -40,6 +40,7 @@ import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.event.AfterConvertCallback; import org.springframework.data.elasticsearch.core.event.AfterSaveCallback; +import org.springframework.data.elasticsearch.core.event.BeforeConvertCallback; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.BulkOptions; import org.springframework.data.elasticsearch.core.query.GetQuery; @@ -66,11 +67,10 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Spy private ValueCapturingAfterSaveCallback afterSaveCallback = new ValueCapturingAfterSaveCallback(); @Spy private ValueCapturingAfterConvertCallback afterConvertCallback = new ValueCapturingAfterConvertCallback(); + @Spy private ValueCapturingBeforeConvertCallback beforeConvertCallback = new ValueCapturingBeforeConvertCallback(); protected final void initTemplate(AbstractElasticsearchTemplate template) { this.template = template; - - this.template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback, afterConvertCallback)); } protected final org.elasticsearch.search.SearchHits nSearchHits(int count) { @@ -82,78 +82,90 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-771 void saveOneShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity = new Person("init", "luke"); Person saved = template.save(entity); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), any()); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity = new Person("init", "luke"); Person saved = template.save(entity, index); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), eq(index)); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveArrayShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); Iterable saved = template.save(entity1, entity2); - verify(afterSaveCallback, times(2)).onAfterSave(any()); + verify(afterSaveCallback, times(2)).onAfterSave(any(), any()); Iterator savedIterator = saved.iterator(); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveIterableShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); Iterable saved = template.save(Arrays.asList(entity1, entity2)); - verify(afterSaveCallback, times(2)).onAfterSave(any()); + verify(afterSaveCallback, times(2)).onAfterSave(any(), any()); Iterator savedIterator = saved.iterator(); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveIterableWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); Iterable saved = template.save(Arrays.asList(entity1, entity2), index); - verify(afterSaveCallback, times(2)).onAfterSave(any()); + verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index)); Iterator savedIterator = saved.iterator(); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); - assertThat(savedIterator.next().getId()).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); + assertThat(savedIterator.next().firstname).isEqualTo("after-save"); } @Test // DATAES-771 void indexShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity = new Person("init", "luke"); IndexQuery indexQuery = indexQueryForEntity(entity); template.index(indexQuery, index); - verify(afterSaveCallback).onAfterSave(eq(entity)); + verify(afterSaveCallback).onAfterSave(eq(entity), eq(index)); Person savedPerson = (Person) indexQuery.getObject(); - assertThat(savedPerson.id).isEqualTo("after-save"); + assertThat(savedPerson.firstname).isEqualTo("after-save"); } private IndexQuery indexQueryForEntity(Person entity) { @@ -165,6 +177,8 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-771 void bulkIndexShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); @@ -172,16 +186,18 @@ abstract class AbstractElasticsearchTemplateCallbackTests { IndexQuery query2 = indexQueryForEntity(entity2); template.bulkIndex(Arrays.asList(query1, query2), index); - verify(afterSaveCallback, times(2)).onAfterSave(any()); + verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index)); Person savedPerson1 = (Person) query1.getObject(); Person savedPerson2 = (Person) query2.getObject(); - assertThat(savedPerson1.getId()).isEqualTo("after-save"); - assertThat(savedPerson2.getId()).isEqualTo("after-save"); + assertThat(savedPerson1.firstname).isEqualTo("after-save"); + assertThat(savedPerson2.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void bulkIndexWithOptionsShouldInvokeAfterSaveCallbacks() { + template.setEntityCallbacks(EntityCallbacks.create(afterSaveCallback)); + Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); @@ -189,20 +205,22 @@ abstract class AbstractElasticsearchTemplateCallbackTests { IndexQuery query2 = indexQueryForEntity(entity2); template.bulkIndex(Arrays.asList(query1, query2), BulkOptions.defaultOptions(), index); - verify(afterSaveCallback, times(2)).onAfterSave(any()); + verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index)); Person savedPerson1 = (Person) query1.getObject(); Person savedPerson2 = (Person) query2.getObject(); - assertThat(savedPerson1.getId()).isEqualTo("after-save"); - assertThat(savedPerson2.getId()).isEqualTo("after-save"); + assertThat(savedPerson1.firstname).isEqualTo("after-save"); + assertThat(savedPerson2.firstname).isEqualTo("after-save"); } @Test // DATAES-772 void getShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + Person result = template.get("init", Person.class); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } private Document lukeDocument() { @@ -212,31 +230,37 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-772 void getWithCoordinatesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + Person result = template.get("init", Person.class, index); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void getViaQueryShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test Person result = template.get(new GetQuery("init"), Person.class, index); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void multiGetShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + List results = template.multiGet(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } private Query queryForTwo() { @@ -246,13 +270,15 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-772 void queryForObjectShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + doReturn(nSearchHits(1)).when(searchResponse).getHits(); @SuppressWarnings("deprecation") // we know what we test Person result = template.queryForObject(queryForOne(), Person.class, index); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } private Query queryForOne() { @@ -262,31 +288,37 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-772 void queryForPageShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test AggregatedPage results = template.queryForPage(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.getContent().get(0).id).isEqualTo("after-convert"); - assertThat(results.getContent().get(1).id).isEqualTo("after-convert"); + assertThat(results.getContent().get(0).firstname).isEqualTo("after-convert"); + assertThat(results.getContent().get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void queryForPageWithMultipleQueriesAndSameEntityClassShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test List> results = template.queryForPage(singletonList(queryForTwo()), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List persons = results.get(0).getContent(); - assertThat(persons.get(0).id).isEqualTo("after-convert"); - assertThat(persons.get(1).id).isEqualTo("after-convert"); + assertThat(persons.get(0).firstname).isEqualTo("after-convert"); + assertThat(persons.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void queryForPageWithMultipleQueriesAndEntityClassesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test List> results = template.queryForPage(singletonList(queryForTwo()), singletonList(Person.class), index); @@ -294,29 +326,33 @@ abstract class AbstractElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List persons = results.get(0).getContent().stream().map(Person.class::cast).collect(Collectors.toList()); - assertThat(persons.get(0).id).isEqualTo("after-convert"); - assertThat(persons.get(1).id).isEqualTo("after-convert"); + assertThat(persons.get(0).firstname).isEqualTo("after-convert"); + assertThat(persons.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void streamShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + CloseableIterator results = template.stream(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.next().id).isEqualTo("after-convert"); - assertThat(results.next().id).isEqualTo("after-convert"); + assertThat(results.next().firstname).isEqualTo("after-convert"); + assertThat(results.next().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchScrollContinueShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + CloseableIterator results = template.stream(queryForTwo(), Person.class, index); skipItemsFromScrollStart(results); - assertThat(results.next().id).isEqualTo("after-convert"); - assertThat(results.next().id).isEqualTo("after-convert"); + assertThat(results.next().firstname).isEqualTo("after-convert"); + assertThat(results.next().firstname).isEqualTo("after-convert"); verify(afterConvertCallback, times(4)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); @@ -330,51 +366,59 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-772 void queryForListShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test List results = template.queryForList(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void queryForListWithMultipleQueriesAndSameEntityClassShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test List> results = template.queryForList(singletonList(queryForTwo()), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List persons = results.get(0); - assertThat(persons.get(0).id).isEqualTo("after-convert"); - assertThat(persons.get(1).id).isEqualTo("after-convert"); + assertThat(persons.get(0).firstname).isEqualTo("after-convert"); + assertThat(persons.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void queryForListWithMultipleQueriesAndEntityClassesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test List> results = template.queryForList(singletonList(queryForTwo()), singletonList(Person.class), index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List persons = results.get(0).stream().map(Person.class::cast).collect(Collectors.toList()); - assertThat(persons.get(0).id).isEqualTo("after-convert"); - assertThat(persons.get(1).id).isEqualTo("after-convert"); + assertThat(persons.get(0).firstname).isEqualTo("after-convert"); + assertThat(persons.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void moreLikeThisShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + @SuppressWarnings("deprecation") // we know what we test AggregatedPage results = template.moreLikeThis(moreLikeThisQuery(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.getContent().get(0).id).isEqualTo("after-convert"); - assertThat(results.getContent().get(1).id).isEqualTo("after-convert"); + assertThat(results.getContent().get(0).firstname).isEqualTo("after-convert"); + assertThat(results.getContent().get(1).firstname).isEqualTo("after-convert"); } private MoreLikeThisQuery moreLikeThisQuery() { @@ -387,115 +431,164 @@ abstract class AbstractElasticsearchTemplateCallbackTests { @Test // DATAES-772 void searchOneShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + doReturn(nSearchHits(1)).when(searchResponse).getHits(); SearchHit result = template.searchOne(queryForOne(), Person.class); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(result.getContent().id).isEqualTo("after-convert"); + assertThat(result.getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchOneWithIndexCoordinatesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + doReturn(nSearchHits(1)).when(searchResponse).getHits(); SearchHit result = template.searchOne(queryForOne(), Person.class, index); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.getContent().id).isEqualTo("after-convert"); + assertThat(result.getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void multiSearchShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + List> results = template.multiSearch(singletonList(queryForTwo()), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List> hits = results.get(0).getSearchHits(); - assertThat(hits.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(hits.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void multiSearchWithMultipleEntityClassesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + List> results = template.multiSearch(singletonList(queryForTwo()), singletonList(Person.class), index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List> hits = results.get(0).getSearchHits(); - assertThat(((Person) hits.get(0).getContent()).id).isEqualTo("after-convert"); - assertThat(((Person) hits.get(1).getContent()).id).isEqualTo("after-convert"); + assertThat(((Person) hits.get(0).getContent()).firstname).isEqualTo("after-convert"); + assertThat(((Person) hits.get(1).getContent()).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHits results = template.search(queryForTwo(), Person.class); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); List> hits = results.getSearchHits(); - assertThat(hits.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(hits.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchWithIndexCoordinatesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHits results = template.search(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List> hits = results.getSearchHits(); - assertThat(hits.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(hits.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchViaMoreLikeThisShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHits results = template.search(moreLikeThisQuery(), Person.class); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); List> hits = results.getSearchHits(); - assertThat(hits.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(hits.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchViaMoreLikeThisWithIndexCoordinatesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHits results = template.search(moreLikeThisQuery(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); List> hits = results.getSearchHits(); - assertThat(hits.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(hits.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(hits.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(hits.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchForStreamShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHitsIterator results = template.searchForStream(queryForTwo(), Person.class); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.next().getContent().id).isEqualTo("after-convert"); - assertThat(results.next().getContent().id).isEqualTo("after-convert"); + assertThat(results.next().getContent().firstname).isEqualTo("after-convert"); + assertThat(results.next().getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchForStreamWithIndexCoordinatesShouldInvokeAfterConvertCallback() { + template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); + SearchHitsIterator results = template.searchForStream(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.next().getContent().id).isEqualTo("after-convert"); - assertThat(results.next().getContent().id).isEqualTo("after-convert"); + assertThat(results.next().getContent().firstname).isEqualTo("after-convert"); + assertThat(results.next().getContent().firstname).isEqualTo("after-convert"); + } + + @Test // DATAES-785 + void saveOneShouldInvokeBeforeConvertCallbacks() { + + template.setEntityCallbacks(EntityCallbacks.create(beforeConvertCallback)); + + Person entity = new Person("init1", "luke1"); + + Person saved = template.save(entity, index); + + verify(beforeConvertCallback).onBeforeConvert(any(), eq(index)); + assertThat(saved.firstname).isEqualTo("before-convert"); + } + + @Test // DATAES-785 + void saveAllShouldInvokeBeforeConvertCallbacks() { + + template.setEntityCallbacks(EntityCallbacks.create(beforeConvertCallback)); + + Person entity1 = new Person("init1", "luke1"); + Person entity2 = new Person("init2", "luke2"); + + Iterable saved = template.save(Arrays.asList(entity1, entity2), index); + + verify(beforeConvertCallback, times(2)).onBeforeConvert(any(), eq(index)); + Iterator iterator = saved.iterator(); + assertThat(iterator.next().firstname).isEqualTo("before-convert"); + assertThat(iterator.next().firstname).isEqualTo("before-convert"); } @Data @@ -530,13 +623,13 @@ abstract class AbstractElasticsearchTemplateCallbackTests { implements AfterSaveCallback { @Override - public Person onAfterSave(Person entity) { + public Person onAfterSave(Person entity, IndexCoordinates index) { capture(entity); return new Person() { { - id = "after-save"; - firstname = entity.firstname; + id = entity.id; + firstname = "after-save"; } }; } @@ -551,8 +644,24 @@ abstract class AbstractElasticsearchTemplateCallbackTests { capture(entity); return new Person() { { - id = "after-convert"; - firstname = entity.firstname; + id = entity.id; + firstname = "after-convert"; + } + }; + } + } + + static class ValueCapturingBeforeConvertCallback extends ValueCapturingEntityCallback + implements BeforeConvertCallback { + + @Override + public Person onBeforeConvert(Person entity, IndexCoordinates indexCoordinates) { + + capture(entity); + return new Person() { + { + id = entity.id; + firstname = "before-convert"; } }; } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java index b682f074b..666fcbf9e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java @@ -46,6 +46,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; @@ -55,6 +56,7 @@ import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsea import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.event.ReactiveAfterConvertCallback; import org.springframework.data.elasticsearch.core.event.ReactiveAfterSaveCallback; +import org.springframework.data.elasticsearch.core.event.ReactiveBeforeConvertCallback; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.Query; @@ -82,6 +84,10 @@ public class ReactiveElasticsearchTemplateCallbackTests { private final IndexCoordinates index = IndexCoordinates.of("index"); + @Spy private ValueCapturingAfterSaveCallback afterSaveCallback = new ValueCapturingAfterSaveCallback(); + @Spy private ValueCapturingAfterConvertCallback afterConvertCallback = new ValueCapturingAfterConvertCallback(); + @Spy private ValueCapturingBeforeConvertCallback beforeConvertCallback = new ValueCapturingBeforeConvertCallback(); + @BeforeEach public void setUp() { template = new ReactiveElasticsearchTemplate(client); @@ -122,104 +128,90 @@ public class ReactiveElasticsearchTemplateCallbackTests { @Test // DATAES-771 void saveOneShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity = new Person("init", "luke"); Person saved = template.save(entity).block(Duration.ofSeconds(1)); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), any()); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveOneFromPublisherShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity = new Person("init", "luke"); Person saved = template.save(Mono.just(entity)).block(Duration.ofSeconds(1)); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), any()); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity = new Person("init", "luke"); - Person saved = template.save(entity, IndexCoordinates.of("index")).block(Duration.ofSeconds(1)); + Person saved = template.save(entity, index).block(Duration.ofSeconds(1)); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), eq(index)); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveFromPublisherWithIndexCoordinatesShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity = new Person("init", "luke"); - Person saved = template.save(Mono.just(entity), IndexCoordinates.of("index")).block(Duration.ofSeconds(1)); + Person saved = template.save(Mono.just(entity), index).block(Duration.ofSeconds(1)); - verify(afterSaveCallback).onAfterSave(eq(entity)); - assertThat(saved.id).isEqualTo("after-save"); + verify(afterSaveCallback).onAfterSave(eq(entity), eq(index)); + assertThat(saved.firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveAllShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); - List saved = template.saveAll(Arrays.asList(entity1, entity2), IndexCoordinates.of("index")).toStream() + List saved = template.saveAll(Arrays.asList(entity1, entity2), index).toStream() .collect(Collectors.toList()); - verify(afterSaveCallback, times(2)).onAfterSave(any()); - assertThat(saved.get(0).getId()).isEqualTo("after-save"); - assertThat(saved.get(1).getId()).isEqualTo("after-save"); + verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index)); + assertThat(saved.get(0).firstname).isEqualTo("after-save"); + assertThat(saved.get(1).firstname).isEqualTo("after-save"); } @Test // DATAES-771 void saveFromMonoAllShouldInvokeAfterSaveCallbacks() { - ValueCapturingAfterSaveCallback afterSaveCallback = spy(new ValueCapturingAfterSaveCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterSaveCallback)); Person entity1 = new Person("init1", "luke1"); Person entity2 = new Person("init2", "luke2"); - List saved = template.saveAll(Mono.just(Arrays.asList(entity1, entity2)), IndexCoordinates.of("index")) + List saved = template.saveAll(Mono.just(Arrays.asList(entity1, entity2)), index) .toStream().collect(Collectors.toList()); - verify(afterSaveCallback, times(2)).onAfterSave(any()); - assertThat(saved.get(0).getId()).isEqualTo("after-save"); - assertThat(saved.get(1).getId()).isEqualTo("after-save"); + verify(afterSaveCallback, times(2)).onAfterSave(any(), eq(index)); + assertThat(saved.get(0).firstname).isEqualTo("after-save"); + assertThat(saved.get(1).firstname).isEqualTo("after-save"); } @Test // DATAES-772 void multiGetShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); List results = template.multiGet(pagedQueryForTwo(), Person.class, index).timeout(Duration.ofSeconds(1)) @@ -227,69 +219,59 @@ public class ReactiveElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void findByIdShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test Person result = template.findById("init", Person.class).block(Duration.ofSeconds(1)); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void findByIdWithIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test Person result = template.findById("init", Person.class, index).block(Duration.ofSeconds(1)); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void getShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); Person result = template.get("init", Person.class).block(Duration.ofSeconds(1)); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void getWithIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); Person result = template.get("init", Person.class, index).block(Duration.ofSeconds(1)); verify(afterConvertCallback).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(result.id).isEqualTo("after-convert"); + assertThat(result.firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void findUsingPageableShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test @@ -297,8 +279,8 @@ public class ReactiveElasticsearchTemplateCallbackTests { .collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } private Query pagedQueryForTwo() { @@ -313,8 +295,6 @@ public class ReactiveElasticsearchTemplateCallbackTests { @Test // DATAES-772 void findUsingScrollShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test @@ -322,8 +302,8 @@ public class ReactiveElasticsearchTemplateCallbackTests { .collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } private Query scrollingQueryForTwo() { @@ -333,8 +313,6 @@ public class ReactiveElasticsearchTemplateCallbackTests { @Test // DATAES-772 void findWithIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test @@ -343,15 +321,13 @@ public class ReactiveElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void findWithReturnTypeShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test @@ -359,15 +335,13 @@ public class ReactiveElasticsearchTemplateCallbackTests { .toStream().collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void findWithReturnTypeAndIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); @SuppressWarnings("deprecation") // we know what we test @@ -376,30 +350,26 @@ public class ReactiveElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).id).isEqualTo("after-convert"); - assertThat(results.get(1).id).isEqualTo("after-convert"); + assertThat(results.get(0).firstname).isEqualTo("after-convert"); + assertThat(results.get(1).firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); List> results = template.search(pagedQueryForTwo(), Person.class).timeout(Duration.ofSeconds(1)) .toStream().collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(results.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(results.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchWithIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); List> results = template.search(pagedQueryForTwo(), Person.class, index) @@ -407,30 +377,26 @@ public class ReactiveElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(results.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(results.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchWithResultTypeShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); List> results = template.search(pagedQueryForTwo(), Person.class, Person.class) .timeout(Duration.ofSeconds(1)).toStream().collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), any()); - assertThat(results.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(results.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(results.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getContent().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 void searchWithResultTypeAndIndexCoordinatesShouldInvokeAfterConvertCallbacks() { - ValueCapturingAfterConvertCallback afterConvertCallback = spy(new ValueCapturingAfterConvertCallback()); - template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); List> results = template.search(pagedQueryForTwo(), Person.class, Person.class, index) @@ -438,8 +404,37 @@ public class ReactiveElasticsearchTemplateCallbackTests { verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).getContent().id).isEqualTo("after-convert"); - assertThat(results.get(1).getContent().id).isEqualTo("after-convert"); + assertThat(results.get(0).getContent().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getContent().firstname).isEqualTo("after-convert"); + } + + @Test // DATAES-785 + void saveOneShouldInvokeBeforeConvertCallbacks() { + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(beforeConvertCallback)); + + Person entity = new Person("init1", "luke1"); + + Person saved = template.save(entity, index).block(Duration.ofSeconds(1)); + + verify(beforeConvertCallback).onBeforeConvert(any(), eq(index)); + assertThat(saved.firstname).isEqualTo("before-convert"); + } + + @Test // DATAES-785 + void saveAllShouldInvokeBeforeConvertCallbacks() { + + template.setEntityCallbacks(ReactiveEntityCallbacks.create(beforeConvertCallback)); + + Person entity1 = new Person("init1", "luke1"); + Person entity2 = new Person("init2", "luke2"); + + List saved = template.saveAll(Arrays.asList(entity1, entity2), index).toStream() + .collect(Collectors.toList()); + + verify(beforeConvertCallback, times(2)).onBeforeConvert(any(), eq(index)); + assertThat(saved.get(0).firstname).isEqualTo("before-convert"); + assertThat(saved.get(1).firstname).isEqualTo("before-convert"); } @Data @@ -474,14 +469,14 @@ public class ReactiveElasticsearchTemplateCallbackTests { implements ReactiveAfterSaveCallback { @Override - public Mono onAfterSave(Person entity) { + public Mono onAfterSave(Person entity, IndexCoordinates index) { return Mono.defer(() -> { capture(entity); Person newPerson = new Person() { { - id = "after-save"; - firstname = entity.firstname; + id = entity.id; + firstname = "after-save"; } }; return Mono.just(newPerson); @@ -499,8 +494,27 @@ public class ReactiveElasticsearchTemplateCallbackTests { capture(entity); Person newPerson = new Person() { { - id = "after-convert"; - firstname = entity.firstname; + id = entity.id; + firstname = "after-convert"; + } + }; + return Mono.just(newPerson); + }); + } + } + + static class ValueCapturingBeforeConvertCallback extends ValueCapturingEntityCallback + implements ReactiveBeforeConvertCallback { + + @Override + public Mono onBeforeConvert(Person entity, IndexCoordinates index) { + + return Mono.defer(() -> { + capture(entity); + Person newPerson = new Person() { + { + id = entity.id; + firstname = "before-convert"; } }; return Mono.just(newPerson); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallbackTests.java index 52dad6ea9..67fe22e4b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/event/AuditingEntityCallbackTests.java @@ -30,12 +30,14 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.lang.Nullable; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ @ExtendWith(MockitoExtension.class) class AuditingEntityCallbackTests { @@ -66,7 +68,7 @@ class AuditingEntityCallbackTests { void shouldCallHandler() { Sample entity = new Sample(); entity.setId("42"); - callback.onBeforeConvert(entity); + callback.onBeforeConvert(entity, IndexCoordinates.of("index")); verify(handler).markAudited(eq(entity)); } @@ -79,7 +81,7 @@ class AuditingEntityCallbackTests { sample2.setId("2"); doReturn(sample2).when(handler).markAudited(any()); - Sample result = (Sample) callback.onBeforeConvert(sample1); + Sample result = (Sample) callback.onBeforeConvert(sample1, IndexCoordinates.of("index")); assertThat(result).isSameAs(sample2); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/event/ElasticsearchOperationsCallbackTest.java b/src/test/java/org/springframework/data/elasticsearch/core/event/ElasticsearchOperationsCallbackTest.java index 0637711c0..0e3755ffb 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/event/ElasticsearchOperationsCallbackTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/event/ElasticsearchOperationsCallbackTest.java @@ -26,10 +26,12 @@ import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.stereotype.Component; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ abstract class ElasticsearchOperationsCallbackTest { @@ -41,7 +43,7 @@ abstract class ElasticsearchOperationsCallbackTest { @Component static class SampleEntityBeforeConvertCallback implements BeforeConvertCallback { @Override - public SampleEntity onBeforeConvert(SampleEntity entity) { + public SampleEntity onBeforeConvert(SampleEntity entity, IndexCoordinates index) { entity.setText("converted"); return entity; } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallbackTests.java index 4d15016c8..3a5c6d3bd 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveAuditingEntityCallbackTests.java @@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core.event; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import reactor.test.StepVerifier; import java.time.LocalDateTime; @@ -38,6 +39,7 @@ import org.springframework.lang.Nullable; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ @ExtendWith(MockitoExtension.class) class ReactiveAuditingEntityCallbackTests { @@ -68,7 +70,7 @@ class ReactiveAuditingEntityCallbackTests { void shouldCallHandler() { Sample entity = new Sample(); entity.setId("42"); - callback.onBeforeConvert(entity); + callback.onBeforeConvert(entity, IndexCoordinates.of("index")); verify(handler).markAudited(eq(entity)); } @@ -81,7 +83,7 @@ class ReactiveAuditingEntityCallbackTests { sample2.setId("2"); doReturn(sample2).when(handler).markAudited(any()); - callback.onBeforeConvert(sample1) // + callback.onBeforeConvert(sample1, IndexCoordinates.of("index")) // .as(StepVerifier::create) // .consumeNextWith(it -> { // assertThat(it).isSameAs(sample2); // diff --git a/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveElasticsearchOperationsCallbackTest.java b/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveElasticsearchOperationsCallbackTest.java index 4ca299b7a..035d4f059 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveElasticsearchOperationsCallbackTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/event/ReactiveElasticsearchOperationsCallbackTest.java @@ -31,6 +31,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; +import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration; import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; @@ -39,6 +40,7 @@ import org.springframework.test.context.ContextConfiguration; /** * @author Peter-Josef Meisch + * @author Roman Puchkovskiy */ @SpringIntegrationTest @ContextConfiguration(classes = { ReactiveElasticsearchOperationsCallbackTest.Config.class }) @@ -50,7 +52,7 @@ public class ReactiveElasticsearchOperationsCallbackTest { @Component static class SampleEntityBeforeConvertCallback implements ReactiveBeforeConvertCallback { @Override - public Mono onBeforeConvert(SampleEntity entity) { + public Mono onBeforeConvert(SampleEntity entity, IndexCoordinates index) { entity.setText("reactive-converted"); return Mono.just(entity); }