DATAJDBC-454 - Adds generics to events.
Events now have a type parameter for the type of aggregate root they relate to. In order to utilize this an react to only events relating to a specific type of entity `AbstractRelationalEventListener` was added. Original pull request: #199.
This commit is contained in:
committed by
Mark Paluch
parent
22f9eded60
commit
5fdfd3a9dc
@@ -401,7 +401,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
|
||||
private <T> T triggerAfterLoad(T entity) {
|
||||
|
||||
publisher.publishEvent(new AfterLoadEvent(entity));
|
||||
publisher.publishEvent(new AfterLoadEvent<>(entity));
|
||||
|
||||
return entityCallbacks.callback(AfterLoadCallback.class, entity);
|
||||
}
|
||||
@@ -412,25 +412,21 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
|
||||
private <T> T triggerBeforeSave(T aggregateRoot, AggregateChange<T> change) {
|
||||
|
||||
publisher.publishEvent(new BeforeSaveEvent( //
|
||||
//
|
||||
aggregateRoot, //
|
||||
//
|
||||
change));
|
||||
publisher.publishEvent(new BeforeSaveEvent<>(aggregateRoot, change));
|
||||
|
||||
return entityCallbacks.callback(BeforeSaveCallback.class, aggregateRoot, change);
|
||||
}
|
||||
|
||||
private <T> T triggerAfterSave(T aggregateRoot, AggregateChange<T> change) {
|
||||
|
||||
publisher.publishEvent(new AfterSaveEvent(aggregateRoot, change));
|
||||
publisher.publishEvent(new AfterSaveEvent<>(aggregateRoot, change));
|
||||
|
||||
return entityCallbacks.callback(AfterSaveCallback.class, aggregateRoot);
|
||||
}
|
||||
|
||||
private <T> void triggerAfterDelete(@Nullable T aggregateRoot, Object id, AggregateChange<?> change) {
|
||||
private <T> void triggerAfterDelete(@Nullable T aggregateRoot, Object id, AggregateChange<T> change) {
|
||||
|
||||
publisher.publishEvent(new AfterDeleteEvent(Identifier.of(id), aggregateRoot, change));
|
||||
publisher.publishEvent(new AfterDeleteEvent<>(Identifier.of(id), aggregateRoot, change));
|
||||
|
||||
if (aggregateRoot != null) {
|
||||
entityCallbacks.callback(AfterDeleteCallback.class, aggregateRoot);
|
||||
@@ -438,9 +434,9 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T triggerBeforeDelete(@Nullable T aggregateRoot, Object id, AggregateChange<?> change) {
|
||||
private <T> T triggerBeforeDelete(@Nullable T aggregateRoot, Object id, AggregateChange<T> change) {
|
||||
|
||||
publisher.publishEvent(new BeforeDeleteEvent(Identifier.of(id), aggregateRoot, change));
|
||||
publisher.publishEvent(new BeforeDeleteEvent<>(Identifier.of(id), aggregateRoot, change));
|
||||
|
||||
if (aggregateRoot != null) {
|
||||
return entityCallbacks.callback(BeforeDeleteCallback.class, aggregateRoot, change);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* Base class for mapping events of Spring Data Relational
|
||||
*
|
||||
* @param <E> the type this event refers to.
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractRelationalEvent<E> extends ApplicationEvent implements RelationalEvent<E> {
|
||||
|
||||
/**
|
||||
* Creates an event with the given source.
|
||||
* The source might be an entity or an id of an entity, depending on the actual event subclass.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
*/
|
||||
public AbstractRelationalEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
|
||||
/**
|
||||
* Base class to implement domain class specific {@link ApplicationListener} classes.
|
||||
*
|
||||
* @param <E>
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AbstractRelationalEventListener<E> implements ApplicationListener<AbstractRelationalEvent<?>> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractRelationalEventListener.class);
|
||||
private final Class<?> domainClass;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractRelationalEventListener}.
|
||||
*/
|
||||
public AbstractRelationalEventListener() {
|
||||
|
||||
Class<?> typeArgument = GenericTypeResolver.resolveTypeArgument(this.getClass(),
|
||||
AbstractRelationalEventListener.class);
|
||||
this.domainClass = typeArgument == null ? Object.class : typeArgument;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractRelationalEvent<?> event) {
|
||||
|
||||
if (!domainClass.isAssignableFrom(event.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event instanceof AfterLoadEvent) {
|
||||
onAfterLoad((AfterLoadEvent<E>) event);
|
||||
} else if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete((AfterDeleteEvent<E>) event);
|
||||
} else if (event instanceof AfterSaveEvent) {
|
||||
onAfterSave((AfterSaveEvent<E>) event);
|
||||
} else if (event instanceof BeforeConvertEvent) {
|
||||
onBeforeConvert((BeforeConvertEvent<E>) event);
|
||||
} else if (event instanceof BeforeDeleteEvent) {
|
||||
onBeforeDelete((BeforeDeleteEvent<E>) event);
|
||||
} else if (event instanceof BeforeSaveEvent) {
|
||||
onBeforeSave((BeforeSaveEvent<E>) event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeConvertEvent}.
|
||||
*
|
||||
* @param event never {@literal null}.
|
||||
*/
|
||||
protected void onBeforeConvert(BeforeConvertEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeConvert({})", event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link BeforeSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onBeforeSave(BeforeSaveEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeSave({})", event.getAggregateChange());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterSaveEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onAfterSave(AfterSaveEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterSave({})", event.getAggregateChange());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterLoadEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onAfterLoad(AfterLoadEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterLoad({})", event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onAfterDelete(AfterDeleteEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterDelete({})", event.getAggregateChange());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture {@link BeforeDeleteEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onBeforeDelete(BeforeDeleteEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeDelete({})", event.getAggregateChange());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,8 +23,9 @@ import org.springframework.lang.Nullable;
|
||||
* not depends on the delete method used.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AfterDeleteEvent extends RelationalDeleteEvent {
|
||||
public class AfterDeleteEvent<E> extends RelationalDeleteEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 2615043444207870206L;
|
||||
|
||||
@@ -34,7 +35,7 @@ public class AfterDeleteEvent extends RelationalDeleteEvent {
|
||||
* @param change the {@link AggregateChange} encoding the actions that were performed on the database as part of the
|
||||
* delete operation. Must not be {@literal null}.
|
||||
*/
|
||||
public AfterDeleteEvent(Identifier id, @Nullable Object instance, AggregateChange<?> change) {
|
||||
public AfterDeleteEvent(Identifier id, @Nullable E instance, AggregateChange<E> change) {
|
||||
super(id, instance, change);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@ package org.springframework.data.relational.core.mapping.event;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class AfterLoadEvent extends RelationalEventWithEntity {
|
||||
public class AfterLoadEvent<E> extends RelationalEventWithEntity<E> {
|
||||
|
||||
private static final long serialVersionUID = 7343072117054666699L;
|
||||
|
||||
/**
|
||||
* @param entity the newly instantiated entity. Must not be {@literal null}.
|
||||
*/
|
||||
public AfterLoadEvent(Object entity) {
|
||||
public AfterLoadEvent(E entity) {
|
||||
super(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.data.relational.core.conversion.AggregateChange;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class AfterSaveEvent extends RelationalSaveEvent {
|
||||
public class AfterSaveEvent<E> extends RelationalSaveEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = 1681164473866370396L;
|
||||
|
||||
@@ -31,7 +31,7 @@ public class AfterSaveEvent extends RelationalSaveEvent {
|
||||
* @param change the {@link AggregateChange} encoding the actions performed on the database as part of the delete.
|
||||
* Must not be {@literal null}.
|
||||
*/
|
||||
public AfterSaveEvent(Object instance, AggregateChange<?> change) {
|
||||
public AfterSaveEvent(E instance, AggregateChange<E> change) {
|
||||
super(instance, change);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.data.relational.core.conversion.AggregateChange;
|
||||
* @since 1.1
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class BeforeConvertEvent extends RelationalSaveEvent {
|
||||
public class BeforeConvertEvent<E> extends RelationalSaveEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = -5716795164911939224L;
|
||||
|
||||
@@ -33,7 +33,7 @@ public class BeforeConvertEvent extends RelationalSaveEvent {
|
||||
* this event is fired before the conversion the change is actually empty, but contains information if the
|
||||
* aggregate is considered new in {@link AggregateChange#getKind()}. Must not be {@literal null}.
|
||||
*/
|
||||
public BeforeConvertEvent(Object instance, AggregateChange<?> change) {
|
||||
public BeforeConvertEvent(E instance, AggregateChange<E> change) {
|
||||
|
||||
super(instance, change);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class BeforeDeleteEvent extends RelationalDeleteEvent {
|
||||
public class BeforeDeleteEvent<E> extends RelationalDeleteEvent<E> {
|
||||
|
||||
private static final long serialVersionUID = -137285843224094551L;
|
||||
|
||||
@@ -33,7 +33,7 @@ public class BeforeDeleteEvent extends RelationalDeleteEvent {
|
||||
* @param entity the entity about to get deleted. May be {@literal null}.
|
||||
* @param change the {@link AggregateChange} encoding the planned actions to be performed on the database.
|
||||
*/
|
||||
public <T> BeforeDeleteEvent(Identifier id, @Nullable Object entity, AggregateChange<?> change) {
|
||||
public BeforeDeleteEvent(Identifier id, @Nullable E entity, AggregateChange<E> change) {
|
||||
super(id, entity, change);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.data.relational.core.conversion.AggregateChange;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class BeforeSaveEvent extends RelationalSaveEvent{
|
||||
public class BeforeSaveEvent<E> extends RelationalSaveEvent<E>{
|
||||
|
||||
private static final long serialVersionUID = -4935804431519314116L;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class BeforeSaveEvent extends RelationalSaveEvent{
|
||||
* @param change the {@link AggregateChange} that is going to get applied to the database. Must not be {@literal null}.
|
||||
*
|
||||
*/
|
||||
public BeforeSaveEvent(Object instance, AggregateChange<?> change) {
|
||||
public BeforeSaveEvent(E instance, AggregateChange<E> change) {
|
||||
super(instance, change);
|
||||
|
||||
}
|
||||
|
||||
@@ -25,22 +25,22 @@ import org.springframework.util.Assert;
|
||||
* {@link AggregateChange} and may also have an entity if the entity was provided to the method performing the delete.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract public class RelationalDeleteEvent extends ApplicationEvent implements WithId, WithAggregateChange {
|
||||
public abstract class RelationalDeleteEvent<E> extends AbstractRelationalEvent<E> implements WithId<E>, WithAggregateChange<E> {
|
||||
|
||||
private static final long serialVersionUID = -8071323168471611098L;
|
||||
|
||||
private final Identifier id;
|
||||
@Nullable private final Object entity;
|
||||
private final AggregateChange<?> change;
|
||||
@Nullable private final E entity;
|
||||
private final AggregateChange<E> change;
|
||||
|
||||
/**
|
||||
* @param id the identifier of the aggregate that gets deleted. Must not be {@literal null}.
|
||||
* @param entity is the aggregate root that gets deleted. Might be {@literal null}.
|
||||
* @param change the {@link AggregateChange} for the deletion containing more detailed information about the deletion
|
||||
* process.
|
||||
*/
|
||||
RelationalDeleteEvent(Identifier id, @Nullable Object entity, AggregateChange<?> change) {
|
||||
RelationalDeleteEvent(Identifier id, @Nullable E entity, AggregateChange<E> change) {
|
||||
|
||||
super(id);
|
||||
|
||||
@@ -59,13 +59,17 @@ abstract public class RelationalDeleteEvent extends ApplicationEvent implements
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getEntity() {
|
||||
public E getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AggregateChange<?> getAggregateChange() {
|
||||
public AggregateChange<E> getAggregateChange() {
|
||||
return change;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends E> getType() {
|
||||
return change.getEntityType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,25 @@ package org.springframework.data.relational.core.mapping.event;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* an event signalling JDBC processing.
|
||||
*
|
||||
* @param <E> the type of the entity to which the event relates.
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public interface RelationalEvent {
|
||||
public interface RelationalEvent<E> {
|
||||
|
||||
/**
|
||||
* @return the entity to which this event refers. Might be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
Object getEntity();
|
||||
E getEntity();
|
||||
|
||||
/**
|
||||
* @return the type of the entity to which the event relates.
|
||||
* @since 2.0
|
||||
*/
|
||||
Class<? extends E> getType();
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ import org.springframework.context.ApplicationEvent;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class RelationalEventWithEntity extends ApplicationEvent implements WithEntity {
|
||||
public class RelationalEventWithEntity<E> extends AbstractRelationalEvent<E> implements WithEntity<E> {
|
||||
|
||||
private static final long serialVersionUID = 4891455396602090638L;
|
||||
private final Object entity;
|
||||
private final E entity;
|
||||
|
||||
RelationalEventWithEntity(Object entity) {
|
||||
RelationalEventWithEntity(E entity) {
|
||||
|
||||
super(entity);
|
||||
|
||||
@@ -38,7 +38,12 @@ public class RelationalEventWithEntity extends ApplicationEvent implements WithE
|
||||
* @return the entity to which this event refers. Guaranteed to be not {@literal null}.
|
||||
*/
|
||||
@Override
|
||||
public Object getEntity() {
|
||||
public E getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends E> getType() {
|
||||
return (Class<? extends E>) entity.getClass();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.data.relational.core.mapping.event;/*
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -13,19 +13,23 @@ package org.springframework.data.relational.core.mapping.event;/*
|
||||
* 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.relational.core.conversion.AggregateChange;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Events triggered during saving of an aggregate.
|
||||
* Events of this type always have an {@link AggregateChange} and an entity.
|
||||
* Events triggered during saving of an aggregate. Events of this type always have an {@link AggregateChange} and an
|
||||
* entity.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class RelationalSaveEvent extends RelationalEventWithEntity implements WithAggregateChange{
|
||||
public abstract class RelationalSaveEvent<E> extends RelationalEventWithEntity<E> implements WithAggregateChange<E> {
|
||||
|
||||
private final AggregateChange<?> change;
|
||||
private final AggregateChange<E> change;
|
||||
|
||||
RelationalSaveEvent(Object entity, AggregateChange<?> change) {
|
||||
RelationalSaveEvent(E entity, AggregateChange<E> change) {
|
||||
|
||||
super(entity);
|
||||
|
||||
@@ -35,7 +39,7 @@ public abstract class RelationalSaveEvent extends RelationalEventWithEntity impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public AggregateChange<?> getAggregateChange() {
|
||||
public AggregateChange<E> getAggregateChange() {
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ import org.springframework.data.relational.core.conversion.AggregateChange;
|
||||
* {@link RelationalEvent} that represents a change to an aggregate and therefore has an {@link AggregateChange}
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public interface WithAggregateChange extends RelationalEvent {
|
||||
public interface WithAggregateChange<E> extends RelationalEvent<E> {
|
||||
|
||||
/**
|
||||
* @return Guaranteed to be not {@literal null}.
|
||||
*/
|
||||
AggregateChange<?> getAggregateChange();
|
||||
AggregateChange<E> getAggregateChange();
|
||||
}
|
||||
|
||||
@@ -15,15 +15,21 @@
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping.event;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
/**
|
||||
* Interface for events which are guaranteed to have an entity.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public interface WithEntity extends RelationalEvent {
|
||||
public interface WithEntity<E> extends RelationalEvent<E> {
|
||||
|
||||
/**
|
||||
* Overridden in order to change nullability.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
Object getEntity();
|
||||
@Override
|
||||
@NonNull
|
||||
E getEntity();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.data.relational.core.mapping.event;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public interface WithId extends RelationalEvent {
|
||||
public interface WithId<E> extends RelationalEvent<E> {
|
||||
|
||||
/**
|
||||
* Events with an identifier will always return a {@link Identifier} one.
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
|
||||
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.Identifier;
|
||||
|
||||
/**
|
||||
* {@link BeforeConvertCallback} to capture auditing information on persisting and updating entities.
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping.event;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.relational.core.conversion.AggregateChange;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractRelationalEventListener}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class AbstractRelationalEventListenerUnitTests {
|
||||
|
||||
List<String> events = new ArrayList<>();
|
||||
EventListenerUnderTest listener = new EventListenerUnderTest();
|
||||
private DummyEntity dummyEntity = new DummyEntity();
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void afterLoad() {
|
||||
|
||||
listener.onApplicationEvent(new AfterLoadEvent<>(dummyEntity));
|
||||
|
||||
assertThat(events).containsExactly("afterLoad");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void beforeConvert() {
|
||||
|
||||
listener.onApplicationEvent(new BeforeConvertEvent<>(dummyEntity, AggregateChange.forDelete(dummyEntity)));
|
||||
|
||||
assertThat(events).containsExactly("beforeConvert");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void beforeSave() {
|
||||
|
||||
listener.onApplicationEvent(new BeforeSaveEvent<>(dummyEntity, AggregateChange.forSave(dummyEntity)));
|
||||
|
||||
assertThat(events).containsExactly("beforeSave");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void afterSave() {
|
||||
|
||||
listener.onApplicationEvent(new AfterSaveEvent<>(dummyEntity, AggregateChange.forDelete(dummyEntity)));
|
||||
|
||||
assertThat(events).containsExactly("afterSave");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void beforeDelete() {
|
||||
|
||||
listener.onApplicationEvent(
|
||||
new BeforeDeleteEvent<>(Identifier.of(23), dummyEntity, AggregateChange.forDelete(dummyEntity)));
|
||||
|
||||
assertThat(events).containsExactly("beforeDelete");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void afterDelete() {
|
||||
|
||||
listener.onApplicationEvent(
|
||||
new AfterDeleteEvent<>(Identifier.of(23), dummyEntity, AggregateChange.forDelete(dummyEntity)));
|
||||
|
||||
assertThat(events).containsExactly("afterDelete");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void eventWithNonMatchingDomainType() {
|
||||
|
||||
String notADummyEntity = "I'm not a dummy entity";
|
||||
|
||||
listener.onApplicationEvent(
|
||||
new AfterDeleteEvent<>(Identifier.of(23), notADummyEntity, AggregateChange.forDelete(notADummyEntity)));
|
||||
|
||||
assertThat(events).isEmpty();
|
||||
}
|
||||
|
||||
static class DummyEntity {
|
||||
|
||||
}
|
||||
|
||||
private class EventListenerUnderTest extends AbstractRelationalEventListener<DummyEntity> {
|
||||
|
||||
@Override
|
||||
protected void onBeforeConvert(BeforeConvertEvent<DummyEntity> event) {
|
||||
events.add("beforeConvert");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeforeSave(BeforeSaveEvent<DummyEntity> event) {
|
||||
events.add("beforeSave");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterSave(AfterSaveEvent<DummyEntity> event) {
|
||||
events.add("afterSave");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterLoad(AfterLoadEvent<DummyEntity> event) {
|
||||
events.add("afterLoad");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterDelete(AfterDeleteEvent<DummyEntity> event) {
|
||||
events.add("afterDelete");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBeforeDelete(BeforeDeleteEvent<DummyEntity> event) {
|
||||
events.add("beforeDelete");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -609,20 +609,33 @@ For example, the following listener gets invoked before an aggregate gets saved:
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public ApplicationListener<BeforeSaveEvent> timeStampingSaveTime() {
|
||||
public ApplicationListener<BeforeSaveEvent> loggingSaves() {
|
||||
|
||||
return event -> {
|
||||
|
||||
Object entity = event.getEntity();
|
||||
if (entity instanceof Category) {
|
||||
Category category = (Category) entity;
|
||||
category.timeStamp();
|
||||
}
|
||||
LOG.info("{} is getting saved.";
|
||||
};
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If you want to handle events only for a specific domain type you may derive your listener from `AbstractRelationalEventListener` and overwrite one or more of the `onXXX` methods,
|
||||
where `XXX` stands for an event type. It will only get invoked for events related to the domain type you used in the declaration and provides typed events, so no casting of the entity is required.
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public class PersonLoadListener extends AbstractRelationalEventListener<Person> {
|
||||
|
||||
@Override
|
||||
protected void onAfterLoad(AfterLoadEvent<Person> personLoad) {
|
||||
LOG.info(personLoad.getEntity().setLoadTimeStamp(new Date());
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The following table describes the available events:
|
||||
|
||||
.Available events
|
||||
|
||||
Reference in New Issue
Block a user