HHH-7478 - Fix and test
This commit is contained in:
parent
8730320ad6
commit
0958313ebc
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue