HHH-7478 - Fix and test

This commit is contained in:
Lukasz Antoniak 2013-02-08 11:15:43 +01:00 committed by Brett Meyer
parent 8730320ad6
commit 0958313ebc
3 changed files with 108 additions and 5 deletions

View File

@ -32,7 +32,9 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -643,7 +645,9 @@ public class ActionQueue {
private static class BeforeTransactionCompletionProcessQueue { private static class BeforeTransactionCompletionProcessQueue {
private SessionImplementor session; private SessionImplementor session;
private List<BeforeTransactionCompletionProcess> processes = new ArrayList<BeforeTransactionCompletionProcess>(); // Concurrency handling required when transaction completion process is dynamically registered
// inside event listener (HHH-7478).
private Queue<BeforeTransactionCompletionProcess> processes = new ConcurrentLinkedQueue<BeforeTransactionCompletionProcess>();
private BeforeTransactionCompletionProcessQueue(SessionImplementor session) { private BeforeTransactionCompletionProcessQueue(SessionImplementor session) {
this.session = session; this.session = session;
@ -675,8 +679,9 @@ public class ActionQueue {
private static class AfterTransactionCompletionProcessQueue { private static class AfterTransactionCompletionProcessQueue {
private SessionImplementor session; private SessionImplementor session;
private Set<String> querySpacesToInvalidate = new HashSet<String>(); private Set<String> querySpacesToInvalidate = new HashSet<String>();
private List<AfterTransactionCompletionProcess> processes // Concurrency handling required when transaction completion process is dynamically registered
= new ArrayList<AfterTransactionCompletionProcess>( INIT_QUEUE_LIST_SIZE * 3 ); // inside event listener (HHH-7478).
private Queue<AfterTransactionCompletionProcess> processes = new ConcurrentLinkedQueue<AfterTransactionCompletionProcess>();
private AfterTransactionCompletionProcessQueue(SessionImplementor session) { private AfterTransactionCompletionProcessQueue(SessionImplementor session) {
this.session = session; this.session = session;

View File

@ -23,17 +23,32 @@
*/ */
package org.hibernate.envers.tools; package org.hibernate.envers.tools;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public class MutableInteger { public class MutableInteger {
private int value; private int value = 0;
public MutableInteger() { public MutableInteger() {
} }
public MutableInteger(int value) {
this.value = value;
}
public int getAndIncrease() { public int getAndIncrease() {
return value++; return value++;
} }
public int get() {
return value;
}
public void set(int value) {
this.value = value;
}
public void increase() {
++value;
}
} }

View File

@ -0,0 +1,83 @@
package org.hibernate.envers.test.integration.basic;
import org.junit.Assert;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
import org.hibernate.envers.test.entities.StrTestEntity;
import org.hibernate.envers.tools.MutableInteger;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class RegisterUserEventListenersTest extends BaseEnversFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { StrTestEntity.class };
}
@Test
@TestForIssue( jiraKey = "HHH-7478" )
public void testTransactionProcessSynchronization() {
final EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
final CountingPostInsertTransactionBoundaryListener listener = new CountingPostInsertTransactionBoundaryListener();
registry.getEventListenerGroup( EventType.POST_INSERT ).appendListener( listener );
Session session = openSession();
session.getTransaction().begin();
StrTestEntity entity = new StrTestEntity( "str1" );
session.save( entity );
session.getTransaction().commit();
session.close();
// Post insert listener invoked three times - before/after insertion of original data,
// revision entity and audit row.
Assert.assertEquals( 3, listener.getBeforeCount() );
Assert.assertEquals( 3, listener.getAfterCount() );
}
private static class CountingPostInsertTransactionBoundaryListener implements PostInsertEventListener {
private final MutableInteger beforeCounter = new MutableInteger();
private final MutableInteger afterCounter = new MutableInteger();
@Override
public void onPostInsert(PostInsertEvent event) {
event.getSession().getActionQueue().registerProcess(new BeforeTransactionCompletionProcess() {
@Override
public void doBeforeTransactionCompletion(SessionImplementor session) {
beforeCounter.increase();
}
});
event.getSession().getActionQueue().registerProcess(new AfterTransactionCompletionProcess() {
@Override
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
afterCounter.increase();
}
});
}
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return true;
}
public int getBeforeCount() {
return beforeCounter.get();
}
public int getAfterCount() {
return afterCounter.get();
}
}
}