A unified entity change-listener across different persistence APIs and implementations.
In almost all back-end systems there is the need to notify or update additional data whenever core data changes. It can be sending a notification event, invalidating cache entries, audit logging or updating a search index to mention a few.
For example Spring has already support for events, and from Spring 4.2 it also has support for send-at-end-of-transaction-events. Further Spring JPA supports auditing, however it does not support fetching the actual data, just who changed it and when. There is no recollection of what was changed.
All the different persistence frameworks have their different APIs for detecting data changes. With Dachs you have one simple, unified API to deal with.
<dependency>
<groupId>com.ethlo.dachs</groupId>
<artifactId>dachs-{impl}</artifactId>
<version>${dachs.version}</version>
</dependency>
The goal is to have a simple, but powerful API to get notifications of all changes to entities, that is created
, updated
and deleted
.
This listener will buffer all events until the transaction is about to commit. preDataChanged
is called just before the transaction is committed. Any exception here will abort the transaction. postDataChanged
is called just after the transaction is committed.
public interface EntityChangeSetListener
{
void preDataChanged(EntityDataChangeSet changeset);
void postDataChanged(EntityDataChangeSet changeset);
}
Both methods gives you an EntityDataChangeSet
whichs holds all operations performed inside the transaction.
public interface EntityDataChangeSet
{
List<EntityDataChange> getCreated();
List<EntityDataChange> getUpdated();
List<EntityDataChange> getDeleted();
boolean isEmpty();
}
public interface EntityChangeListener
{
void preCreate(EntityDataChange entityData);
void preUpdate(EntityDataChange entityData);
void preDelete(EntityDataChange entityData);
void created(EntityDataChange entityData);
void updated(EntityDataChange entityData);
void deleted(EntityDataChange entityData);
}
Using this simple listener, we get an EntityDataChange
object for each operation on the entity.
public interface EntityDataChange
{
Serializable getId();
Object getEntity();
List<PropertyChange<?>> getPropertyChanges();
Optional<PropertyChange<?>> getPropertyChange(String propertyName);
}
Each EntityDataChange
object holds a collection of PropertyChange
s that is the individual properties that has changed.
public interface PropertyChange<T>
{
String getPropertyName();
Class<T> getPropertyType();
T getOldValue();
T getNewValue();
}
Given a simple Person object:
public class Person()
{
private String name;
private Integer age;
}
EntityData
propertyChanges:
* name - null => "John Doe"
* age - null => 34
EntityData
propertyChanges:
* name - "John Doe" => "John Smith"
* age - 34 => 47
EntityData
propertyChanges:
* name - "John Smith" => null
* age - 47 => null
Dachs relies on the persistence framework in use to notify about operations and there might be limitations.
In general bulk delete will not trigger delete events (aka DELETE FROM Entity
).