From 19bde340c61aa130eeb6a73afe35c737ef834f8a Mon Sep 17 00:00:00 2001 From: Lukasz Antoniak Date: Sat, 25 Aug 2012 16:31:31 +0200 Subject: [PATCH] EntityTrackingRevisionListener extension --- .../EntityTrackingRevisionListener.java | 5 +- .../BaseEnversCollectionEventListener.java | 6 +- .../EnversPostDeleteEventListenerImpl.java | 3 +- .../EnversPostInsertEventListenerImpl.java | 3 +- .../EnversPostUpdateEventListenerImpl.java | 3 +- .../DefaultRevisionInfoGenerator.java | 8 +- ...ModifiedEntitiesRevisionInfoGenerator.java | 6 +- .../revisioninfo/RevisionInfoGenerator.java | 6 +- .../synchronization/EntityChangeNotifier.java | 4 +- .../work/AbstractAuditWorkUnit.java | 10 +- .../synchronization/work/AddWorkUnit.java | 10 +- .../synchronization/work/AuditWorkUnit.java | 1 + .../work/CollectionChangeWorkUnit.java | 2 +- .../synchronization/work/DelWorkUnit.java | 6 +- .../FakeBidirectionalRelationWorkUnit.java | 9 +- .../synchronization/work/ModWorkUnit.java | 4 +- .../PersistentCollectionChangeWorkUnit.java | 10 +- .../CustomTrackingRevisionListener.java | 4 +- .../test/integration/manytomany/BasicMap.java | 37 ++++- .../test/integration/onetomany/BasicList.java | 32 +++- .../detached/JoinColumnBidirectionalList.java | 32 +++- .../NotificationCheckRevisionListener.java | 137 ++++++++++++++++++ 22 files changed, 289 insertions(+), 49 deletions(-) create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/tools/NotificationCheckRevisionListener.java diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/EntityTrackingRevisionListener.java b/hibernate-envers/src/main/java/org/hibernate/envers/EntityTrackingRevisionListener.java index 0366b7f183f4..3d8557b1ed53 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/EntityTrackingRevisionListener.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/EntityTrackingRevisionListener.java @@ -15,9 +15,10 @@ public interface EntityTrackingRevisionListener extends RevisionListener { * @param entityName Name of the audited entity. May be useful when Java class is mapped multiple times, * potentially to different tables. * @param entityId Identifier of modified entity. + * @param entity The actual entity or persistent collection that has changed. * @param revisionType Modification type (addition, update or removal). * @param revisionEntity An instance of the entity annotated with {@link RevisionEntity}. */ - void entityChanged(Class entityClass, String entityName, Serializable entityId, RevisionType revisionType, - Object revisionEntity); + void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionEntity); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/BaseEnversCollectionEventListener.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/BaseEnversCollectionEventListener.java index c79a3c61340e..7ff7b2966f80 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/BaseEnversCollectionEventListener.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/BaseEnversCollectionEventListener.java @@ -100,7 +100,8 @@ protected final void onCollectionAction( collectionEntry, oldColl, event.getAffectedOwnerIdOrNull(), - referencingPropertyName + referencingPropertyName, + event.getCollection() ); auditProcess.addWorkUnit( workUnit ); @@ -196,7 +197,8 @@ private void generateFakeBidirecationalRelationWorkUnits( rd, revType, changeData.getChangedElementIndex(), - nestedWorkUnit + nestedWorkUnit, + event.getCollection() ) ); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostDeleteEventListenerImpl.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostDeleteEventListenerImpl.java index 9a80ae803c58..07594dc83e69 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostDeleteEventListenerImpl.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostDeleteEventListenerImpl.java @@ -56,7 +56,8 @@ public void onPostDelete(PostDeleteEvent event) { getAuditConfiguration(), event.getId(), event.getPersister(), - event.getDeletedState() + event.getDeletedState(), + event.getEntity() ); auditProcess.addWorkUnit( workUnit ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostInsertEventListenerImpl.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostInsertEventListenerImpl.java index 7819b5b549c7..4b93be97ff16 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostInsertEventListenerImpl.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostInsertEventListenerImpl.java @@ -55,7 +55,8 @@ public void onPostInsert(PostInsertEvent event) { getAuditConfiguration(), event.getId(), event.getPersister(), - event.getState() + event.getState(), + event.getEntity() ); auditProcess.addWorkUnit( workUnit ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostUpdateEventListenerImpl.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostUpdateEventListenerImpl.java index d14819b3e447..b723f83ccd80 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostUpdateEventListenerImpl.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversPostUpdateEventListenerImpl.java @@ -59,7 +59,8 @@ public void onPostUpdate(PostUpdateEvent event) { event.getId(), event.getPersister(), newDbState, - event.getOldState() + event.getOldState(), + event.getEntity() ); auditProcess.addWorkUnit( workUnit ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java index f55eddf6d77e..55143e1fa528 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java @@ -98,11 +98,11 @@ public Object generate() { return revisionInfo; } - public void entityChanged(Class entityClass, String entityName, Serializable entityId, RevisionType revisionType, - Object revisionInfo) { + public void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionInfo) { if (listener instanceof EntityTrackingRevisionListener) { - ((EntityTrackingRevisionListener) listener).entityChanged(entityClass, entityName, entityId, revisionType, - revisionInfo); + ((EntityTrackingRevisionListener) listener).entityChanged(entityClass, entityName, entityId, entity, + revisionType, revisionInfo); } } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultTrackingModifiedEntitiesRevisionInfoGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultTrackingModifiedEntitiesRevisionInfoGenerator.java index e63b0b767d74..d26cbbef10ee 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultTrackingModifiedEntitiesRevisionInfoGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultTrackingModifiedEntitiesRevisionInfoGenerator.java @@ -34,9 +34,9 @@ public DefaultTrackingModifiedEntitiesRevisionInfoGenerator(String revisionInfoE @Override @SuppressWarnings({"unchecked"}) - public void entityChanged(Class entityClass, String entityName, Serializable entityId, RevisionType revisionType, - Object revisionEntity) { - super.entityChanged(entityClass, entityName, entityId, revisionType, revisionEntity); + public void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionEntity) { + super.entityChanged(entityClass, entityName, entityId, entity, revisionType, revisionEntity); Set modifiedEntityNames = (Set) modifiedEntityNamesGetter.get(revisionEntity); if (modifiedEntityNames == null) { modifiedEntityNames = new HashSet(); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java index ff0860590067..cfe921987845 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java @@ -37,8 +37,8 @@ public interface RevisionInfoGenerator { Object generate(); /** - * @see EntityTrackingRevisionListener#entityChanged(Class, String, Serializable, RevisionType, Object) + * @see EntityTrackingRevisionListener#entityChanged(Class, String, Serializable, Object, RevisionType, Object) */ - void entityChanged(Class entityClass, String entityName, Serializable entityId, RevisionType revisionType, - Object revisionEntity); + void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionEntity); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/EntityChangeNotifier.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/EntityChangeNotifier.java index 1cc89e763691..e2eed1dacdda 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/EntityChangeNotifier.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/EntityChangeNotifier.java @@ -37,7 +37,7 @@ public void entityChanged(Session session, Object currentRevisionData, AuditWork entityId = ((PersistentCollectionChangeWorkUnit.PersistentCollectionChangeWorkUnitId) entityId).getOwnerId(); } Class entityClass = Tools.getEntityClass(sessionImplementor, session, vwu.getEntityName()); - revisionInfoGenerator.entityChanged(entityClass, vwu.getEntityName(), entityId, vwu.getRevisionType(), - currentRevisionData); + revisionInfoGenerator.entityChanged(entityClass, vwu.getEntityName(), entityId, vwu.getEntity(), + vwu.getRevisionType(), currentRevisionData); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java index 1cc9373cd8eb..d91739740c7c 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AbstractAuditWorkUnit.java @@ -43,6 +43,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit { protected final SessionImplementor sessionImplementor; protected final AuditConfiguration verCfg; protected final Serializable id; + protected final Object entity; protected final String entityName; protected final AuditStrategy auditStrategy; protected final RevisionType revisionType; @@ -50,10 +51,11 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit { private Object performedData; protected AbstractAuditWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, - Serializable id, RevisionType revisionType) { + Serializable id, RevisionType revisionType, Object entity) { this.sessionImplementor = sessionImplementor; this.verCfg = verCfg; this.id = id; + this.entity = entity; this.entityName = entityName; this.revisionType = revisionType; this.auditStrategy = verCfg.getAuditStrategy(); @@ -82,7 +84,11 @@ public Serializable getEntityId() { return id; } - public boolean isPerformed() { + public Object getEntity() { + return entity; + } + + public boolean isPerformed() { return performedData != null; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AddWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AddWorkUnit.java index 507756690e19..7b03bdc76466 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AddWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AddWorkUnit.java @@ -41,8 +41,8 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit private final Map data; public AddWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, - Serializable id, EntityPersister entityPersister, Object[] state) { - super(sessionImplementor, entityName, verCfg, id, RevisionType.ADD); + Serializable id, EntityPersister entityPersister, Object[] state, Object entity) { + super(sessionImplementor, entityName, verCfg, id, RevisionType.ADD, entity); this.data = new HashMap(); this.state = state; @@ -51,8 +51,8 @@ public AddWorkUnit(SessionImplementor sessionImplementor, String entityName, Aud } public AddWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, - Serializable id, Map data) { - super(sessionImplementor, entityName, verCfg, id, RevisionType.ADD); + Serializable id, Map data, Object entity) { + super(sessionImplementor, entityName, verCfg, id, RevisionType.ADD, entity); this.data = data; final String[] propertyNames = sessionImplementor.getFactory().getEntityPersister(getEntityName()).getPropertyNames(); @@ -77,7 +77,7 @@ public AuditWorkUnit merge(AddWorkUnit second) { } public AuditWorkUnit merge(ModWorkUnit second) { - return new AddWorkUnit(sessionImplementor, entityName, verCfg, id, second.getData()); + return new AddWorkUnit(sessionImplementor, entityName, verCfg, id, second.getData(), second.getEntity()); } public AuditWorkUnit merge(DelWorkUnit second) { diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AuditWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AuditWorkUnit.java index eb50f80ab8c2..67ec038e5654 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AuditWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AuditWorkUnit.java @@ -35,6 +35,7 @@ public interface AuditWorkUnit extends WorkUnitMergeVisitor, WorkUnitMergeDispatcher { Serializable getEntityId(); String getEntityName(); + Object getEntity(); boolean containsWork(); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java index f28270f74b15..158152f6f328 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java @@ -42,7 +42,7 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A public CollectionChangeWorkUnit(SessionImplementor session, String entityName, String collectionPropertyName, AuditConfiguration verCfg, Serializable id, Object entity) { - super(session, entityName, verCfg, id, RevisionType.MOD); + super(session, entityName, verCfg, id, RevisionType.MOD, entity); this.entity = entity; this.collectionPropertyName = collectionPropertyName; diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java index 98771d32d625..6ada9558cd8d 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java @@ -42,8 +42,8 @@ public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit private final String[] propertyNames; public DelWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, - Serializable id, EntityPersister entityPersister, Object[] state) { - super(sessionImplementor, entityName, verCfg, id, RevisionType.DEL); + Serializable id, EntityPersister entityPersister, Object[] state, Object entity) { + super(sessionImplementor, entityName, verCfg, id, RevisionType.DEL, entity); this.state = state; this.entityPersister = entityPersister; @@ -73,7 +73,7 @@ public AuditWorkUnit merge(AddWorkUnit second) { if (Tools.arraysEqual(second.getState(), state)) { return null; // Return null if object's state has not changed. } - return new ModWorkUnit(sessionImplementor, entityName, verCfg, id, entityPersister, second.getState(), state); + return new ModWorkUnit(sessionImplementor, entityName, verCfg, id, entityPersister, second.getState(), state, entity); } public AuditWorkUnit merge(ModWorkUnit second) { diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java index eaa2c25efcda..9b74c3cba9a0 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java @@ -27,9 +27,8 @@ public FakeBidirectionalRelationWorkUnit(SessionImplementor sessionImplementor, AuditConfiguration verCfg, Serializable id, String referencingPropertyName, Object owningEntity, RelationDescription rd, RevisionType revisionType, - Object index, - AuditWorkUnit nestedWorkUnit) { - super(sessionImplementor, entityName, verCfg, id, revisionType); + Object index, AuditWorkUnit nestedWorkUnit, Object entity) { + super(sessionImplementor, entityName, verCfg, id, revisionType, entity); this.nestedWorkUnit = nestedWorkUnit; // Adding the change for the relation. @@ -40,14 +39,14 @@ public FakeBidirectionalRelationWorkUnit(SessionImplementor sessionImplementor, public FakeBidirectionalRelationWorkUnit(FakeBidirectionalRelationWorkUnit original, Map fakeRelationChanges, AuditWorkUnit nestedWorkUnit) { - super(original.sessionImplementor, original.entityName, original.verCfg, original.id, original.revisionType); + super(original.sessionImplementor, original.entityName, original.verCfg, original.id, original.revisionType, nestedWorkUnit.getEntity()); this.fakeRelationChanges = fakeRelationChanges; this.nestedWorkUnit = nestedWorkUnit; } public FakeBidirectionalRelationWorkUnit(FakeBidirectionalRelationWorkUnit original, AuditWorkUnit nestedWorkUnit) { - super(original.sessionImplementor, original.entityName, original.verCfg, original.id, original.revisionType); + super(original.sessionImplementor, original.entityName, original.verCfg, original.id, original.revisionType, nestedWorkUnit.getEntity()); this.nestedWorkUnit = nestedWorkUnit; diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/ModWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/ModWorkUnit.java index 927cd2fb0f2b..5f3930036c4e 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/ModWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/ModWorkUnit.java @@ -39,8 +39,8 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit private final boolean changes; public ModWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, - Serializable id, EntityPersister entityPersister, Object[] newState, Object[] oldState) { - super(sessionImplementor, entityName, verCfg, id, RevisionType.MOD); + Serializable id, EntityPersister entityPersister, Object[] newState, Object[] oldState, Object entity) { + super(sessionImplementor, entityName, verCfg, id, RevisionType.MOD, entity); data = new HashMap(); changes = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data, diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java index d3103eb31965..6b3baffd2cf2 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java @@ -47,8 +47,8 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im public PersistentCollectionChangeWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration auditCfg, PersistentCollection collection, CollectionEntry collectionEntry, Serializable snapshot, Serializable id, - String referencingPropertyName) { - super(sessionImplementor, entityName, auditCfg, new PersistentCollectionChangeWorkUnitId(id, collectionEntry.getRole()), RevisionType.MOD); + String referencingPropertyName, Object entity) { + super(sessionImplementor, entityName, auditCfg, new PersistentCollectionChangeWorkUnitId(id, collectionEntry.getRole()), RevisionType.MOD, entity); this.referencingPropertyName = referencingPropertyName; @@ -59,8 +59,8 @@ public PersistentCollectionChangeWorkUnit(SessionImplementor sessionImplementor, public PersistentCollectionChangeWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, Serializable id, List collectionChanges, - String referencingPropertyName) { - super(sessionImplementor, entityName, verCfg, id, RevisionType.MOD); + String referencingPropertyName, Object entity) { + super(sessionImplementor, entityName, verCfg, id, RevisionType.MOD, entity); this.collectionChanges = collectionChanges; this.referencingPropertyName = referencingPropertyName; @@ -156,7 +156,7 @@ public AuditWorkUnit dispatch(WorkUnitMergeVisitor first) { mergedChanges.addAll(newChangesIdMap.values()); return new PersistentCollectionChangeWorkUnit(sessionImplementor, entityName, verCfg, id, mergedChanges, - referencingPropertyName); + referencingPropertyName, entity); } else { throw new RuntimeException("Trying to merge a " + first + " with a PersitentCollectionChangeWorkUnit. " + "This is not really possible."); diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/CustomTrackingRevisionListener.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/CustomTrackingRevisionListener.java index 510be1a43ad4..8a1b627d4469 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/CustomTrackingRevisionListener.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/entities/reventity/trackmodifiedentities/CustomTrackingRevisionListener.java @@ -10,8 +10,8 @@ */ public class CustomTrackingRevisionListener implements EntityTrackingRevisionListener { @Override - public void entityChanged(Class entityClass, String entityName, Serializable entityId, RevisionType revisionType, - Object revisionEntity) { + public void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionEntity) { ((CustomTrackingRevisionEntity)revisionEntity).addModifiedEntityType(entityClass.getName()); } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/BasicMap.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/BasicMap.java index 5114856e4bbe..211198d028de 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/BasicMap.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/manytomany/BasicMap.java @@ -26,16 +26,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Map; import javax.persistence.EntityManager; import org.junit.Test; +import org.hibernate.envers.RevisionType; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.manytomany.MapOwnedEntity; import org.hibernate.envers.test.entities.manytomany.MapOwningEntity; +import org.hibernate.envers.test.tools.NotificationCheckRevisionListener; import org.hibernate.envers.test.tools.TestTools; +import static org.hibernate.envers.test.tools.NotificationCheckRevisionListener.expectNotification; + /** * @author Adam Warski (adam at warski dot org) */ @@ -51,7 +56,12 @@ protected Class[] getAnnotatedClasses() { return new Class[] { MapOwningEntity.class, MapOwnedEntity.class }; } - @Test + @Override + protected void addConfigOptions(Map options) { + options.put( "org.hibernate.envers.revision_listener", NotificationCheckRevisionListener.class.getName() ); + } + + @Test @Priority(10) public void initData() { EntityManager em = getEntityManager(); @@ -72,7 +82,14 @@ public void initData() { em.persist(ing1); em.persist(ing2); + expectNotification( MapOwnedEntity.class, ed1.getId(), ed1, RevisionType.ADD ); + expectNotification( MapOwnedEntity.class, ed2.getId(), ed2, RevisionType.ADD ); + expectNotification( MapOwningEntity.class, ing1.getId(), ing1, RevisionType.ADD ); + expectNotification( MapOwningEntity.class, ing2.getId(), ing2, RevisionType.ADD ); + expectNotification( MapOwningEntity.class, ing2.getId(), TestTools.makeMap( "2", ed2 ), RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // Revision 2 (ing1: adding two mappings, ing2: replacing an existing mapping) @@ -88,7 +105,15 @@ public void initData() { ing2.getReferences().put("2", ed1); + expectNotification( MapOwningEntity.class, ing1.getId(), TestTools.makeMap( "1", ed1, "2", ed1 ), RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing1.getId(), ing1, RevisionType.MOD ); + expectNotification( MapOwnedEntity.class, ed1.getId(), ed1, RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing2.getId(), TestTools.makeMap( "2", ed1 ), RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing2.getId(), ing2, RevisionType.MOD ); + expectNotification( MapOwnedEntity.class, ed2.getId(), ed2, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // No revision (ing1: adding an existing mapping, ing2: removing a non existing mapping) em.getTransaction().begin(); @@ -101,6 +126,7 @@ public void initData() { ing2.getReferences().remove("3"); em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // Revision 3 (ing1: clearing, ing2: replacing with a new map) em.getTransaction().begin(); @@ -112,7 +138,16 @@ public void initData() { ing2.setReferences(new HashMap()); ing2.getReferences().put("1", ed2); + expectNotification( MapOwningEntity.class, ing2.getId(), ing2, RevisionType.MOD ); + expectNotification( MapOwnedEntity.class, ed1.getId(), ed1, RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing1.getId(), TestTools.makeMap(), RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing1.getId(), ing1, RevisionType.MOD ); + expectNotification( MapOwningEntity.class, ing2.getId(), TestTools.makeMap( "1", ed2 ), RevisionType.MOD ); + expectNotification( MapOwnedEntity.class, ed2.getId(),ed2, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); + // ed1_id = ed1.getId(); diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicList.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicList.java index f1935f0c11df..14a0bd6961c4 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicList.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/BasicList.java @@ -24,16 +24,21 @@ package org.hibernate.envers.test.integration.onetomany; import java.util.Arrays; +import java.util.Map; import javax.persistence.EntityManager; import org.junit.Test; -import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase ; +import org.hibernate.envers.RevisionType; +import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.onetomany.ListRefEdEntity; import org.hibernate.envers.test.entities.onetomany.ListRefIngEntity; +import org.hibernate.envers.test.tools.NotificationCheckRevisionListener; import org.hibernate.envers.test.tools.TestTools; +import static org.hibernate.envers.test.tools.NotificationCheckRevisionListener.expectNotification; + /** * @author Adam Warski (adam at warski dot org) */ @@ -49,7 +54,12 @@ protected Class[] getAnnotatedClasses() { return new Class[] { ListRefEdEntity.class, ListRefIngEntity.class }; } - @Test + @Override + protected void addConfigOptions(Map options) { + options.put( "org.hibernate.envers.revision_listener", NotificationCheckRevisionListener.class.getName() ); + } + + @Test @Priority(10) public void initData() { EntityManager em = getEntityManager(); @@ -69,7 +79,13 @@ public void initData() { em.persist(ing1); em.persist(ing2); + expectNotification( ListRefEdEntity.class, ed1.getId(), ed1, RevisionType.ADD ); + expectNotification( ListRefEdEntity.class, ed2.getId(), ed2, RevisionType.ADD ); + expectNotification( ListRefIngEntity.class, ing1.getId(), ing1, RevisionType.ADD ); + expectNotification( ListRefIngEntity.class, ing2.getId(), ing2, RevisionType.ADD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // Revision 2 em.getTransaction().begin(); @@ -79,7 +95,12 @@ public void initData() { ing1.setReference(ed2); + expectNotification( ListRefIngEntity.class, ing1.getId(), ing1, RevisionType.MOD ); + expectNotification( ListRefEdEntity.class, ed2.getId(), ed2, RevisionType.MOD ); + expectNotification( ListRefEdEntity.class, ed1.getId(), ed1, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // Revision 3 em.getTransaction().begin(); @@ -89,9 +110,14 @@ public void initData() { ing2.setReference(ed2); + expectNotification( ListRefIngEntity.class, ing2.getId(), ing2, RevisionType.MOD ); + expectNotification( ListRefEdEntity.class, ed2.getId(), ed2, RevisionType.MOD ); + expectNotification( ListRefEdEntity.class, ed1.getId(), ed1, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); - // + // ed1_id = ed1.getId(); ed2_id = ed2.getId(); diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/JoinColumnBidirectionalList.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/JoinColumnBidirectionalList.java index 27221556a55e..97504dc3022a 100644 --- a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/JoinColumnBidirectionalList.java +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/JoinColumnBidirectionalList.java @@ -24,15 +24,19 @@ package org.hibernate.envers.test.integration.onetomany.detached; import java.util.Arrays; +import java.util.Map; import javax.persistence.EntityManager; import org.junit.Test; +import org.hibernate.envers.RevisionType; import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; import org.hibernate.envers.test.Priority; import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidirectionalRefEdEntity; import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidirectionalRefIngEntity; +import org.hibernate.envers.test.tools.NotificationCheckRevisionListener; +import static org.hibernate.envers.test.tools.NotificationCheckRevisionListener.expectNotification; import static org.hibernate.envers.test.tools.TestTools.checkList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -54,7 +58,12 @@ protected Class[] getAnnotatedClasses() { return new Class[] { ListJoinColumnBidirectionalRefIngEntity.class, ListJoinColumnBidirectionalRefEdEntity.class }; } - @Test + @Override + protected void addConfigOptions(Map options) { + options.put( "org.hibernate.envers.revision_listener", NotificationCheckRevisionListener.class.getName() ); + } + + @Test @Priority(10) public void createData() { EntityManager em = getEntityManager(); @@ -73,7 +82,13 @@ public void createData() { em.persist(ing1); em.persist(ing2); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing1.getId(), ing1, RevisionType.ADD ); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing2.getId(), ing2, RevisionType.ADD ); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed1.getId(), ed1, RevisionType.ADD ); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed2.getId(), ed2, RevisionType.ADD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); // Revision 2 (ing1: ed1, ed2) em.getTransaction().begin(); @@ -86,7 +101,12 @@ public void createData() { ing2.getReferences().remove(ed2); ing1.getReferences().add(ed2); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing1.getId(), ing1, RevisionType.MOD ); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed2.getId(), ed2, RevisionType.ADD ); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing2.getId(), ing2, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); em.clear(); // No revision - no changes @@ -100,6 +120,7 @@ public void createData() { ed2.setOwner(ing2); em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); em.clear(); // Revision 3 (ing1: ed1, ed2) @@ -111,7 +132,10 @@ public void createData() { // Shouldn't get written ed1.setOwner(ing2); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed1.getId(), ed1, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); em.clear(); // Revision 4 (ing2: ed1, ed2) @@ -124,7 +148,13 @@ public void createData() { ing2.getReferences().add(ed1); ing2.getReferences().add(ed2); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing1.getId(), ing1, RevisionType.MOD ); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed1.getId(), ed1, RevisionType.DEL ); + expectNotification( ListJoinColumnBidirectionalRefEdEntity.class, ed2.getId(), ed2, RevisionType.DEL ); + expectNotification( ListJoinColumnBidirectionalRefIngEntity.class, ing2.getId(), ing2, RevisionType.MOD ); + em.getTransaction().commit(); + NotificationCheckRevisionListener.checkAllExpectedNotificationsProcessed(); em.clear(); // diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/NotificationCheckRevisionListener.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/NotificationCheckRevisionListener.java new file mode 100644 index 000000000000..8ae278012b5e --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/tools/NotificationCheckRevisionListener.java @@ -0,0 +1,137 @@ +package org.hibernate.envers.test.tools; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.Queue; + +import junit.framework.Assert; + +import org.hibernate.envers.EntityTrackingRevisionListener; +import org.hibernate.envers.RevisionType; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class NotificationCheckRevisionListener implements EntityTrackingRevisionListener { + private final static Queue expectedNotifications = new LinkedList(); + + public static void expectNotification(Class entityClass, Serializable entityId, Object entity, + RevisionType revisionType) { + expectedNotifications.offer( new ChangeNotification( entityClass, entityId, entity, revisionType ) ); + } + + public static void checkAllExpectedNotificationsProcessed() { + Assert.assertTrue( expectedNotifications.isEmpty() ); + } + + @Override + public void entityChanged(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType, Object revisionEntity) { + ChangeNotification notification = expectedNotifications.poll(); + if ( notification != null ) { + Assert.assertEquals( notification.entityClass, entityClass ); + Assert.assertEquals( notification.entityName, entityName ); + Assert.assertEquals( notification.entityId, entityId ); + System.out.println("1: " + notification.entity.getClass().getName()); + System.out.println("2: " + entity.getClass().getName()); + Assert.assertEquals( notification.entity, entity ); + Assert.assertEquals( notification.revisionType, revisionType ); + } + else { + Assert.fail(); + } + } + + @Override + public void newRevision(Object revisionEntity) { + Assert.assertTrue( !expectedNotifications.isEmpty() ); + } + + private static class ChangeNotification { + private final Class entityClass; + private final String entityName; + private final Serializable entityId; + private final Object entity; + private final RevisionType revisionType; + + public ChangeNotification(Class entityClass, Serializable entityId, Object entity, + RevisionType revisionType) { + this(entityClass, entityClass.getName(), entityId, entity, revisionType); + } + + public ChangeNotification(Class entityClass, String entityName, Serializable entityId, Object entity, + RevisionType revisionType) { + this.entityClass = entityClass; + this.entityName = entityName; + this.entityId = entityId; + this.entity = entity; + this.revisionType = revisionType; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !( o instanceof ChangeNotification) ) { + return false; + } + + ChangeNotification that = (ChangeNotification) o; + + if ( entity != null ? !entity.equals( that.entity ) : that.entity != null ) { + return false; + } + if ( entityClass != null ? !entityClass.equals( that.entityClass ) : that.entityClass != null ) { + return false; + } + if ( entityId != null ? !entityId.equals( that.entityId ) : that.entityId != null ) { + return false; + } + if ( entityName != null ? !entityName.equals( that.entityName ) : that.entityName != null ) { + return false; + } + if ( revisionType != that.revisionType ) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = entityClass != null ? entityClass.hashCode() : 0; + result = 31 * result + ( entityName != null ? entityName.hashCode() : 0 ); + result = 31 * result + ( entityId != null ? entityId.hashCode() : 0 ); + result = 31 * result + ( entity != null ? entity.hashCode() : 0 ); + result = 31 * result + ( revisionType != null ? revisionType.hashCode() : 0 ); + return result; + } + + @Override + public String toString() { + return "ChangeNotification(entityClass = " + entityClass + ", entityName = " + entityName + ", entityId = " + + entityId + ", entity = " + entity + ", revisionType = " + revisionType + ")"; + } + + public Class getEntityClass() { + return entityClass; + } + + public String getEntityName() { + return entityName; + } + + public Serializable getEntityId() { + return entityId; + } + + public Object getEntity() { + return entity; + } + + public RevisionType getRevisionType() { + return revisionType; + } + } +}