Skip to content

Introducing AfterConvertCallback/Event #1060

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

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data Relational Parent</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-jdbc-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-jdbc</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public <T> T findById(Object id, Class<T> domainType) {

T entity = accessStrategy.findById(id, domainType);
if (entity != null) {
return triggerAfterLoad(entity);
return triggerAfterConvert(entity);
}
return entity;
}
Expand Down Expand Up @@ -236,7 +236,7 @@ public <T> Iterable<T> findAll(Class<T> domainType, Sort sort) {
Assert.notNull(domainType, "Domain type must not be null!");

Iterable<T> all = accessStrategy.findAll(domainType, sort);
return triggerAfterLoad(all);
return triggerAfterConvert(all);
}

/*
Expand All @@ -248,7 +248,7 @@ public <T> Page<T> findAll(Class<T> domainType, Pageable pageable) {

Assert.notNull(domainType, "Domain type must not be null!");

Iterable<T> items = triggerAfterLoad(accessStrategy.findAll(domainType, pageable));
Iterable<T> items = triggerAfterConvert(accessStrategy.findAll(domainType, pageable));
List<T> content = StreamSupport.stream(items.spliterator(), false).collect(Collectors.toList());

return PageableExecutionUtils.getPage(content, pageable, () -> accessStrategy.count(domainType));
Expand All @@ -264,7 +264,7 @@ public <T> Iterable<T> findAll(Class<T> domainType) {
Assert.notNull(domainType, "Domain type must not be null!");

Iterable<T> all = accessStrategy.findAll(domainType);
return triggerAfterLoad(all);
return triggerAfterConvert(all);
}

/*
Expand All @@ -278,7 +278,7 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
Assert.notNull(domainType, "Domain type must not be null!");

Iterable<T> allById = accessStrategy.findAllById(ids, domainType);
return triggerAfterLoad(allById);
return triggerAfterConvert(allById);
}

/*
Expand Down Expand Up @@ -385,22 +385,24 @@ private MutableAggregateChange<?> createDeletingChange(Class<?> domainType) {
return aggregateChange;
}

private <T> Iterable<T> triggerAfterLoad(Iterable<T> all) {
private <T> Iterable<T> triggerAfterConvert(Iterable<T> all) {

List<T> result = new ArrayList<>();

for (T e : all) {
result.add(triggerAfterLoad(e));
result.add(triggerAfterConvert(e));
}

return result;
}

private <T> T triggerAfterLoad(T entity) {
private <T> T triggerAfterConvert(T entity) {

publisher.publishEvent(new AfterLoadEvent<>(entity));
publisher.publishEvent(new AfterConvertEvent<>(entity));

return entityCallbacks.callback(AfterLoadCallback.class, entity);
entity = entityCallbacks.callback(AfterLoadCallback.class, entity);
return entityCallbacks.callback(AfterConvertCallback.class, entity);
}

private <T> T triggerBeforeConvert(T aggregateRoot) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback;
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
import org.springframework.data.repository.core.NamedQueries;
Expand Down Expand Up @@ -157,9 +159,11 @@ public T mapRow(ResultSet rs, int rowNum) throws SQLException {
if (entity != null) {

publisher.publishEvent(new AfterLoadEvent<>(entity));
publisher.publishEvent(new AfterConvertEvent<>(entity));

if (callbacks != null) {
return callbacks.callback(AfterLoadCallback.class, entity);
entity = callbacks.callback(AfterLoadCallback.class, entity);
return callbacks.callback(AfterConvertCallback.class, entity);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.NamingStrategy;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback;
import org.springframework.data.relational.core.mapping.event.AfterDeleteCallback;
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
import org.springframework.data.relational.core.mapping.event.AfterSaveCallback;
Expand Down Expand Up @@ -136,7 +137,9 @@ public void callbackOnLoad() {
when(dataAccessStrategy.findAll(SampleEntity.class)).thenReturn(asList(alfred1, neumann1));

when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);

Iterable<SampleEntity> all = template.findAll(SampleEntity.class);

Expand All @@ -158,12 +161,16 @@ public void callbackOnLoadSorted() {
when(dataAccessStrategy.findAll(SampleEntity.class, Sort.by("name"))).thenReturn(asList(alfred1, neumann1));

when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);

Iterable<SampleEntity> all = template.findAll(SampleEntity.class, Sort.by("name"));

verify(callbacks).callback(AfterLoadCallback.class, alfred1);
verify(callbacks).callback(AfterConvertCallback.class, alfred2);
verify(callbacks).callback(AfterLoadCallback.class, neumann1);
verify(callbacks).callback(AfterConvertCallback.class, neumann2);

assertThat(all).containsExactly(alfred2, neumann2);
}
Expand All @@ -180,12 +187,16 @@ public void callbackOnLoadPaged() {
when(dataAccessStrategy.findAll(SampleEntity.class, PageRequest.of(0, 20))).thenReturn(asList(alfred1, neumann1));

when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);

Iterable<SampleEntity> all = template.findAll(SampleEntity.class, PageRequest.of(0, 20));

verify(callbacks).callback(AfterLoadCallback.class, alfred1);
verify(callbacks).callback(AfterConvertCallback.class, alfred2);
verify(callbacks).callback(AfterLoadCallback.class, neumann1);
verify(callbacks).callback(AfterConvertCallback.class, neumann2);

assertThat(all).containsExactly(alfred2, neumann2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.springframework.data.jdbc.testing.TestConfiguration;
import org.springframework.data.jdbc.testing.TestDatabaseFeatures;
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent;
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.core.NamedQueries;
Expand Down Expand Up @@ -309,7 +310,7 @@ public void queryMethodShouldEmitEvents() {

repository.findAllWithSql();

assertThat(eventListener.events).hasSize(1).hasOnlyElementsOfType(AfterLoadEvent.class);
assertThat(eventListener.events).hasSize(2).hasOnlyElementsOfTypes(AfterLoadEvent.class, AfterConvertEvent.class);
}

@Test // DATAJDBC-318
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,7 @@
import org.springframework.data.relational.core.dialect.H2Dialect;
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.event.AfterDeleteEvent;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
import org.springframework.data.relational.core.mapping.event.AfterSaveEvent;
import org.springframework.data.relational.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.relational.core.mapping.event.BeforeDeleteEvent;
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
import org.springframework.data.relational.core.mapping.event.Identifier;
import org.springframework.data.relational.core.mapping.event.RelationalEvent;
import org.springframework.data.relational.core.mapping.event.WithId;
import org.springframework.data.relational.core.mapping.event.*;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
Expand Down Expand Up @@ -198,7 +190,9 @@ public void publishesEventsOnFindAll() {
.extracting(e -> (Class) e.getClass()) //
.containsExactly( //
AfterLoadEvent.class, //
AfterLoadEvent.class //
AfterConvertEvent.class, //
AfterLoadEvent.class, //
AfterConvertEvent.class //
);
}

Expand All @@ -217,7 +211,9 @@ public void publishesEventsOnFindAllById() {
.extracting(e -> (Class) e.getClass()) //
.containsExactly( //
AfterLoadEvent.class, //
AfterLoadEvent.class //
AfterConvertEvent.class, //
AfterLoadEvent.class, //
AfterConvertEvent.class //
);
}

Expand All @@ -234,7 +230,8 @@ public void publishesEventsOnFindById() {
assertThat(publisher.events) //
.extracting(e -> (Class) e.getClass()) //
.containsExactly( //
AfterLoadEvent.class //
AfterLoadEvent.class, //
AfterConvertEvent.class //
);
}

Expand All @@ -253,7 +250,9 @@ public void publishesEventsOnFindAllSorted() {
.extracting(e -> (Class) e.getClass()) //
.containsExactly( //
AfterLoadEvent.class, //
AfterLoadEvent.class //
AfterConvertEvent.class, //
AfterLoadEvent.class, //
AfterConvertEvent.class //
);
}

Expand All @@ -273,7 +272,9 @@ public void publishesEventsOnFindAllPaged() {
.extracting(e -> (Class) e.getClass()) //
.containsExactly( //
AfterLoadEvent.class, //
AfterLoadEvent.class //
AfterConvertEvent.class, //
AfterLoadEvent.class, //
AfterConvertEvent.class //
);
}

Expand Down
4 changes: 2 additions & 2 deletions spring-data-relational/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-relational</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>

<name>Spring Data Relational</name>
<description>Spring Data Relational support</description>

<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>2.3.0-SNAPSHOT</version>
<version>2.3.0-1053-rename-after-load-to-after-convert-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public void onApplicationEvent(AbstractRelationalEvent<?> event) {

if (event instanceof AfterLoadEvent) {
onAfterLoad((AfterLoadEvent<E>) event);
} else if (event instanceof AfterConvertEvent) {
onAfterConvert((AfterConvertEvent<E>) event);
} else if (event instanceof AfterDeleteEvent) {
onAfterDelete((AfterDeleteEvent<E>) event);
} else if (event instanceof AfterSaveEvent) {
Expand Down Expand Up @@ -110,6 +112,7 @@ protected void onAfterSave(AfterSaveEvent<E> event) {
* Captures {@link AfterLoadEvent}.
*
* @param event will never be {@literal null}.
* @deprecated use {@link #onAfterConvert(AfterConvertEvent)} instead.
*/
protected void onAfterLoad(AfterLoadEvent<E> event) {

Expand All @@ -118,6 +121,18 @@ protected void onAfterLoad(AfterLoadEvent<E> event) {
}
}

/**
* Captures {@link AfterConvertEvent}.
*
* @param event will never be {@literal null}.
*/
protected void onAfterConvert(AfterConvertEvent<E> event) {

if (LOG.isDebugEnabled()) {
LOG.debug("onAfterConvert({})", event.getEntity());
}
}

/**
* Captures {@link AfterDeleteEvent}.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2019-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.core.mapping.event;

import org.springframework.data.mapping.callback.EntityCallback;

/**
* An {@link EntityCallback} that gets invoked after an aggregate was converted from the database into an entity.
*
* @author Jens Schauder
* @since 2.6
*/
@FunctionalInterface
public interface AfterConvertCallback<T> extends EntityCallback<T> {

/**
* Entity callback method invoked after an aggregate root was converted. Can return either the same or a modified
* instance of the domain object.
*
* @param aggregate the converted aggregate.
* @return the converted and possibly modified aggregate.
*/
T onAfterConvert(T aggregate);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2017-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.core.mapping.event;

/**
* Gets published after instantiation and setting of all the properties of an entity. This allows to do some
* postprocessing of entities if the entities are mutable. For immutable entities use {@link AfterConvertCallback}.
*
* @author Jens Schauder
* @since 2.6
*/
public class AfterConvertEvent<E> extends RelationalEventWithEntity<E> {

private static final long serialVersionUID = 7343072117054666699L;

/**
* @param entity the newly instantiated entity. Must not be {@literal null}.
*/
public AfterConvertEvent(E entity) {
super(entity);
}
}
Loading