Skip to content

Commit 0958313

Browse files
lukasz-antoniakbrmeyer
authored andcommitted
HHH-7478 - Fix and test
1 parent 8730320 commit 0958313

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
import java.util.HashSet;
3333
import java.util.LinkedList;
3434
import java.util.List;
35+
import java.util.Queue;
3536
import java.util.Set;
37+
import java.util.concurrent.ConcurrentLinkedQueue;
3638

3739
import org.jboss.logging.Logger;
3840

@@ -643,7 +645,9 @@ public static ActionQueue deserialize(
643645

644646
private static class BeforeTransactionCompletionProcessQueue {
645647
private SessionImplementor session;
646-
private List<BeforeTransactionCompletionProcess> processes = new ArrayList<BeforeTransactionCompletionProcess>();
648+
// Concurrency handling required when transaction completion process is dynamically registered
649+
// inside event listener (HHH-7478).
650+
private Queue<BeforeTransactionCompletionProcess> processes = new ConcurrentLinkedQueue<BeforeTransactionCompletionProcess>();
647651

648652
private BeforeTransactionCompletionProcessQueue(SessionImplementor session) {
649653
this.session = session;
@@ -675,8 +679,9 @@ public void beforeTransactionCompletion() {
675679
private static class AfterTransactionCompletionProcessQueue {
676680
private SessionImplementor session;
677681
private Set<String> querySpacesToInvalidate = new HashSet<String>();
678-
private List<AfterTransactionCompletionProcess> processes
679-
= new ArrayList<AfterTransactionCompletionProcess>( INIT_QUEUE_LIST_SIZE * 3 );
682+
// Concurrency handling required when transaction completion process is dynamically registered
683+
// inside event listener (HHH-7478).
684+
private Queue<AfterTransactionCompletionProcess> processes = new ConcurrentLinkedQueue<AfterTransactionCompletionProcess>();
680685

681686
private AfterTransactionCompletionProcessQueue(SessionImplementor session) {
682687
this.session = session;

hibernate-envers/src/main/java/org/hibernate/envers/tools/MutableInteger.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,32 @@
2323
*/
2424
package org.hibernate.envers.tools;
2525

26-
2726
/**
2827
* @author Adam Warski (adam at warski dot org)
2928
*/
3029
public class MutableInteger {
31-
private int value;
30+
private int value = 0;
3231

3332
public MutableInteger() {
3433
}
3534

35+
public MutableInteger(int value) {
36+
this.value = value;
37+
}
38+
3639
public int getAndIncrease() {
3740
return value++;
3841
}
42+
43+
public int get() {
44+
return value;
45+
}
46+
47+
public void set(int value) {
48+
this.value = value;
49+
}
50+
51+
public void increase() {
52+
++value;
53+
}
3954
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.hibernate.envers.test.integration.basic;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import org.hibernate.Session;
7+
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
8+
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
9+
import org.hibernate.engine.spi.SessionImplementor;
10+
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
11+
import org.hibernate.envers.test.entities.StrTestEntity;
12+
import org.hibernate.envers.tools.MutableInteger;
13+
import org.hibernate.event.service.spi.EventListenerRegistry;
14+
import org.hibernate.event.spi.EventType;
15+
import org.hibernate.event.spi.PostInsertEvent;
16+
import org.hibernate.event.spi.PostInsertEventListener;
17+
import org.hibernate.persister.entity.EntityPersister;
18+
import org.hibernate.testing.TestForIssue;
19+
20+
/**
21+
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
22+
*/
23+
public class RegisterUserEventListenersTest extends BaseEnversFunctionalTestCase {
24+
@Override
25+
protected Class<?>[] getAnnotatedClasses() {
26+
return new Class<?>[] { StrTestEntity.class };
27+
}
28+
29+
@Test
30+
@TestForIssue( jiraKey = "HHH-7478" )
31+
public void testTransactionProcessSynchronization() {
32+
final EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
33+
final CountingPostInsertTransactionBoundaryListener listener = new CountingPostInsertTransactionBoundaryListener();
34+
35+
registry.getEventListenerGroup( EventType.POST_INSERT ).appendListener( listener );
36+
37+
Session session = openSession();
38+
session.getTransaction().begin();
39+
StrTestEntity entity = new StrTestEntity( "str1" );
40+
session.save( entity );
41+
session.getTransaction().commit();
42+
session.close();
43+
44+
// Post insert listener invoked three times - before/after insertion of original data,
45+
// revision entity and audit row.
46+
Assert.assertEquals( 3, listener.getBeforeCount() );
47+
Assert.assertEquals( 3, listener.getAfterCount() );
48+
}
49+
50+
private static class CountingPostInsertTransactionBoundaryListener implements PostInsertEventListener {
51+
private final MutableInteger beforeCounter = new MutableInteger();
52+
private final MutableInteger afterCounter = new MutableInteger();
53+
54+
@Override
55+
public void onPostInsert(PostInsertEvent event) {
56+
event.getSession().getActionQueue().registerProcess(new BeforeTransactionCompletionProcess() {
57+
@Override
58+
public void doBeforeTransactionCompletion(SessionImplementor session) {
59+
beforeCounter.increase();
60+
}
61+
});
62+
event.getSession().getActionQueue().registerProcess(new AfterTransactionCompletionProcess() {
63+
@Override
64+
public void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
65+
afterCounter.increase();
66+
}
67+
});
68+
}
69+
70+
@Override
71+
public boolean requiresPostCommitHanding(EntityPersister persister) {
72+
return true;
73+
}
74+
75+
public int getBeforeCount() {
76+
return beforeCounter.get();
77+
}
78+
79+
public int getAfterCount() {
80+
return afterCounter.get();
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)