diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java index 094973f5ae..69aa2562e9 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java @@ -34,6 +34,7 @@ import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitDeleteEventListener; import org.hibernate.event.spi.PostDeleteEvent; import org.hibernate.event.spi.PostDeleteEventListener; import org.hibernate.event.spi.PreDeleteEvent; @@ -170,7 +171,7 @@ public class EntityDeleteAction extends EntityAction { } } - private void postCommitDelete() { + private void postCommitDelete(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_DELETE ); if ( listenerGroup.isEmpty() ) { return; @@ -182,8 +183,19 @@ public class EntityDeleteAction extends EntityAction { getPersister(), eventSource() ); - for( PostDeleteEventListener listener : listenerGroup.listeners() ){ - listener.onPostDelete( event ); + for ( PostDeleteEventListener listener : listenerGroup.listeners() ) { + if ( PostCommitDeleteEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostDelete( event ); + } + else { + ((PostCommitDeleteEventListener) listener).onPostDeleteCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostDelete( event ); + } } } @@ -197,7 +209,7 @@ public class EntityDeleteAction extends EntityAction { ); getPersister().getCacheAccessStrategy().unlockItem( ck, lock ); } - postCommitDelete(); + postCommitDelete( success ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java index b6a0f280b7..50ce35e162 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java @@ -31,6 +31,7 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitInsertEventListener; import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -149,7 +150,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction if ( success && persister.hasCache() && !persister.isCacheInvalidationRequired() ) { persister.getCache().afterInsert( getGeneratedId(), cacheEntry ); }*/ - postCommitInsert(); + postCommitInsert( success ); } private void postInsert() { @@ -173,7 +174,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction } } - private void postCommitInsert() { + private void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -186,7 +187,18 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { - listener.onPostInsert( event ); + if ( PostCommitInsertEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostInsert( event ); + } + else { + ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostInsert( event ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java index 19fc0809c4..87d35bb034 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java @@ -36,6 +36,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitInsertEventListener; import org.hibernate.event.spi.PostInsertEvent; import org.hibernate.event.spi.PostInsertEventListener; import org.hibernate.event.spi.PreInsertEvent; @@ -177,7 +178,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { } } - private void postCommitInsert() { + private void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -190,7 +191,18 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { eventSource() ); for ( PostInsertEventListener listener : listenerGroup.listeners() ) { - listener.onPostInsert( event ); + if ( PostCommitInsertEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostInsert( event ); + } + else { + ((PostCommitInsertEventListener) listener).onPostInsertCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostInsert( event ); + } } } @@ -220,7 +232,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { .secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() ); } } - postCommitInsert(); + postCommitInsert( success ); } private boolean cacheAfterInsert(EntityPersister persister, CacheKey ck) { diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java index 85af4a6dcf..5d7caec0f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java @@ -39,6 +39,7 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitUpdateEventListener; import org.hibernate.event.spi.PostUpdateEvent; import org.hibernate.event.spi.PostUpdateEventListener; import org.hibernate.event.spi.PreUpdateEvent; @@ -277,7 +278,7 @@ public final class EntityUpdateAction extends EntityAction { } } - private void postCommitUpdate() { + private void postCommitUpdate(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_UPDATE ); if ( listenerGroup.isEmpty() ) { return; @@ -292,7 +293,18 @@ public final class EntityUpdateAction extends EntityAction { eventSource() ); for ( PostUpdateEventListener listener : listenerGroup.listeners() ) { - listener.onPostUpdate( event ); + if ( PostCommitUpdateEventListener.class.isInstance( listener ) ) { + if ( success ) { + listener.onPostUpdate( event ); + } + else { + ((PostCommitUpdateEventListener) listener).onPostUpdateCommitFailed( event ); + } + } + else { + //default to the legacy implementation that always fires the event + listener.onPostUpdate( event ); + } } } @@ -330,7 +342,7 @@ public final class EntityUpdateAction extends EntityAction { persister.getCacheAccessStrategy().unlockItem( ck, lock ); } } - postCommitUpdate(); + postCommitUpdate( success ); } private boolean cacheAfterUpdate(EntityPersister persister, CacheKey ck) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java new file mode 100644 index 0000000000..dd49d43300 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitDeleteEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity delete is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitDeleteEventListener extends PostDeleteEventListener { + /** + * Called when a commit fails and an an entity was scheduled for deletion + * + * @param event the delete event to be handled + */ + public void onPostDeleteCommitFailed(PostDeleteEvent event); +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java new file mode 100644 index 0000000000..f2d4f0f477 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitInsertEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity insert is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitInsertEventListener extends PostInsertEventListener { + /** + * Called when a commit fails and an an entity was scheduled for insertion + * + * @param event the insert event to be handled + */ + public void onPostInsertCommitFailed(PostInsertEvent event); +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java new file mode 100644 index 0000000000..3fb27823c1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/spi/PostCommitUpdateEventListener.java @@ -0,0 +1,15 @@ +package org.hibernate.event.spi; + +/** + * Called after an entity update is committed to the datastore. + * + * @author Shawn Clowater + */ +public interface PostCommitUpdateEventListener extends PostUpdateEventListener { + /** + * Called when a commit fails and an an entity was scheduled for update + * + * @param event the update event to be handled + */ + public void onPostUpdateCommitFailed(PostUpdateEvent event); +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java new file mode 100644 index 0000000000..c180c366d9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/events/LegacyPostCommitListenerTest.java @@ -0,0 +1,265 @@ +package org.hibernate.test.events; + +import org.hibernate.IrrelevantEntity; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.*; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test to ensure that the existing post commit behavior when using plain PostXEventListeners fire on both success and failure. + * + * @author ShawnClowater + */ +public class LegacyPostCommitListenerTest extends BaseCoreFunctionalTestCase { + private PostInsertEventListener postCommitInsertEventListener = new LegacyPostCommitInsertEventListener(); + private PostDeleteEventListener postCommitDeleteEventListener = new LegacyPostCommitDeleteEventListener(); + private PostUpdateEventListener postCommitUpdateEventListener = new LegacyPostCommitUpdateEventListener(); + + @Override + protected void prepareTest() throws Exception { + ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired = 0; + ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired = 0; + ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired = 0; + } + + @Override + protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) { + super.prepareBootstrapRegistryBuilder( builder ); + builder.with( + new Integrator() { + + @Override + public void integrate( + Configuration configuration, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + @Override + public void integrate( + MetadataImplementor metadata, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + private void integrate(SessionFactoryServiceRegistry serviceRegistry) { + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_DELETE + ).appendListener( postCommitDeleteEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_UPDATE + ).appendListener( postCommitUpdateEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_INSERT + ).appendListener( postCommitInsertEventListener ); + } + + @Override + public void disintegrate( + SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + } + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.rollback(); + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitInsertEventListener) postCommitInsertEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitUpdateEventListener) postCommitUpdateEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + //the legacy implementation fires the listener on failure as well + Assert.assertEquals( 1, ((LegacyPostCommitDeleteEventListener) postCommitDeleteEventListener).fired ); + } + + private class LegacyPostCommitDeleteEventListener implements PostDeleteEventListener { + int fired; + + @Override + public void onPostDelete(PostDeleteEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class LegacyPostCommitUpdateEventListener implements PostUpdateEventListener { + int fired; + + @Override + public void onPostUpdate(PostUpdateEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class LegacyPostCommitInsertEventListener implements PostInsertEventListener { + int fired; + + @Override + public void onPostInsert(PostInsertEvent event) { + fired++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {IrrelevantEntity.class}; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java b/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java new file mode 100644 index 0000000000..ca4d007451 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/events/PostCommitListenerTest.java @@ -0,0 +1,298 @@ +package org.hibernate.test.events; + +import org.hibernate.IrrelevantEntity; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.PostCommitDeleteEventListener; +import org.hibernate.event.spi.PostCommitInsertEventListener; +import org.hibernate.event.spi.PostCommitUpdateEventListener; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostInsertEventListener; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +import org.junit.Assert; +import org.junit.Test; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +/** + * Test to ensure that the existing post commit behavior when using plain PostXEventListeners fire on both success and failure. + * + * @author ShawnClowater + */ +public class PostCommitListenerTest extends BaseCoreFunctionalTestCase { + private PostInsertEventListener postCommitInsertEventListener = new TestPostCommitInsertEventListener(); + private PostDeleteEventListener postCommitDeleteEventListener = new TestPostCommitDeleteEventListener(); + private PostUpdateEventListener postCommitUpdateEventListener = new TestPostCommitUpdateEventListener(); + + @Override + protected void prepareTest() throws Exception { + ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success = 0; + ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed = 0; + ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success = 0; + ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed = 0; + ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess = 0; + ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed = 0; + } + + @Override + protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) { + super.prepareBootstrapRegistryBuilder( builder ); + builder.with( + new Integrator() { + + @Override + public void integrate( + Configuration configuration, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + @Override + public void integrate( + MetadataImplementor metadata, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + integrate( serviceRegistry ); + } + + private void integrate(SessionFactoryServiceRegistry serviceRegistry) { + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_DELETE + ).appendListener( postCommitDeleteEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_UPDATE + ).appendListener( postCommitUpdateEventListener ); + serviceRegistry.getService( EventListenerRegistry.class ).getEventListenerGroup( + EventType.POST_COMMIT_INSERT + ).appendListener( postCommitInsertEventListener ); + } + + @Override + public void disintegrate( + SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + } + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success ); + Assert.assertEquals( 0, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitInsertListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.rollback(); + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).success ); + Assert.assertEquals( 1, ((TestPostCommitInsertEventListener) postCommitInsertEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess ); + Assert.assertEquals( 0, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitUpdateListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + irrelevantEntity.setName( "Irrelevant 2" ); + session.update( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).sucess ); + Assert.assertEquals( 1, ((TestPostCommitUpdateEventListener) postCommitUpdateEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerSuccess() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.commit(); + + session.close(); + + Assert.assertEquals( 1, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success ); + Assert.assertEquals( 0, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed ); + } + + @Test + @TestForIssue(jiraKey = "HHH-1582") + public void testPostCommitDeleteListenerRollback() { + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + + IrrelevantEntity irrelevantEntity = new IrrelevantEntity(); + irrelevantEntity.setName( "Irrelevant" ); + + session.save( irrelevantEntity ); + session.flush(); + transaction.commit(); + session.close(); + + session = openSession(); + transaction = session.beginTransaction(); + session.delete( irrelevantEntity ); + session.flush(); + transaction.rollback(); + + session.close(); + + Assert.assertEquals( 0, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).success ); + Assert.assertEquals( 1, ((TestPostCommitDeleteEventListener) postCommitDeleteEventListener).failed ); + } + + private class TestPostCommitDeleteEventListener implements PostCommitDeleteEventListener { + int success; + int failed; + + @Override + public void onPostDelete(PostDeleteEvent event) { + success++; + } + + @Override + public void onPostDeleteCommitFailed(PostDeleteEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class TestPostCommitUpdateEventListener implements PostCommitUpdateEventListener { + int sucess; + int failed; + + @Override + public void onPostUpdate(PostUpdateEvent event) { + sucess++; + } + + @Override + public void onPostUpdateCommitFailed(PostUpdateEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + private class TestPostCommitInsertEventListener implements PostCommitInsertEventListener { + int success; + int failed; + + @Override + public void onPostInsert(PostInsertEvent event) { + success++; + } + + @Override + public void onPostInsertCommitFailed(PostInsertEvent event) { + failed++; + } + + @Override + public boolean requiresPostCommitHanding(EntityPersister persister) { + return true; + } + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {IrrelevantEntity.class}; + } +}