Skip to content

Commit 335ddea

Browse files
committed
HHH-8254 throw HibernateException when transaction is rolledback by a
reaper thread Conflicts: hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/transaction/TransactionJoiningTest.java
1 parent e361ad4 commit 335ddea

File tree

2 files changed

+36
-18
lines changed

2 files changed

+36
-18
lines changed

hibernate-core/src/main/java/org/hibernate/engine/transaction/synchronization/internal/SynchronizationCallbackCoordinatorImpl.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import javax.transaction.SystemException;
2727

28+
import org.hibernate.HibernateException;
2829
import org.hibernate.TransactionException;
2930
import org.hibernate.cfg.Settings;
3031
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
@@ -55,9 +56,9 @@ public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCa
5556
private AfterCompletionAction afterCompletionAction;
5657
private ExceptionMapper exceptionMapper;
5758

58-
private long registrationThreadId;
59+
private volatile long registrationThreadId;
5960
private final int NO_STATUS = -1;
60-
private int delayedCompletionHandlingStatus;
61+
private volatile int delayedCompletionHandlingStatus;
6162

6263
public SynchronizationCallbackCoordinatorImpl(TransactionCoordinator transactionCoordinator) {
6364
this.transactionCoordinator = transactionCoordinator;
@@ -153,11 +154,12 @@ public void delayedAfterCompletion() {
153154
if ( delayedCompletionHandlingStatus != NO_STATUS ) {
154155
doAfterCompletion( delayedCompletionHandlingStatus );
155156
delayedCompletionHandlingStatus = NO_STATUS;
157+
throw new HibernateException("Transaction was rolled back in a different thread!");
156158
}
157159
}
158160

159161
private void doAfterCompletion(int status) {
160-
LOG.tracev( "Transaction after completion callback [status={0}]", status );
162+
LOG.tracev( "Transaction afterCompletion callback [status={0}]", status );
161163

162164
try {
163165
afterCompletionAction.doAction( transactionCoordinator, status );

hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/transaction/TransactionJoiningTest.java

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,26 @@
2323
*/
2424
package org.hibernate.ejb.test.transaction;
2525

26-
import static org.junit.Assert.assertEquals;
2726
import static org.junit.Assert.assertFalse;
2827
import static org.junit.Assert.assertTrue;
2928

3029
import java.util.Map;
3130
import java.util.concurrent.CountDownLatch;
3231

3332
import javax.persistence.EntityManager;
33+
import javax.persistence.PersistenceException;
3434
import javax.transaction.Status;
3535
import javax.transaction.Synchronization;
3636

37+
import org.hibernate.HibernateException;
3738
import org.hibernate.Session;
3839
import org.hibernate.Transaction;
3940
import org.hibernate.ejb.AvailableSettings;
4041
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
4142
import org.hibernate.engine.spi.SessionImplementor;
4243
import org.hibernate.engine.transaction.internal.jta.CMTTransaction;
4344
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
45+
import org.hibernate.exception.GenericJDBCException;
4446
import org.hibernate.internal.SessionImpl;
4547
import org.hibernate.testing.TestForIssue;
4648
import org.hibernate.testing.jta.TestingJtaBootstrap;
@@ -186,32 +188,46 @@ public void afterCompletion( int i ) {
186188
* See HHH-7910
187189
*/
188190
@Test
189-
@TestForIssue(jiraKey="HHH-7910")
191+
@TestForIssue(jiraKey = "HHH-7910")
190192
public void testMultiThreadTransactionTimeout() throws Exception {
191193
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
192-
194+
193195
EntityManager em = entityManagerFactory().createEntityManager();
194196
final SessionImpl sImpl = em.unwrap( SessionImpl.class );
195-
196-
final CountDownLatch latch = new CountDownLatch(1);
197-
197+
198+
final CountDownLatch latch = new CountDownLatch( 1 );
199+
198200
Thread thread = new Thread() {
199201
public void run() {
200-
sImpl.getTransactionCoordinator().getSynchronizationCallbackCoordinator().afterCompletion( Status.STATUS_ROLLEDBACK );
202+
sImpl.getTransactionCoordinator().getSynchronizationCallbackCoordinator()
203+
.afterCompletion( Status.STATUS_ROLLEDBACK );
201204
latch.countDown();
202205
}
203206
};
204207
thread.start();
205-
208+
206209
latch.await();
207-
208-
em.persist( new Book( "The Book of Foo", 1 ) );
209-
210-
// Ensure that the session was cleared by the background thread.
211-
assertEquals( "The background thread did not clear the session as expected!",
212-
0, em.createQuery( "from Book" ).getResultList().size() );
213210

214-
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
211+
boolean caught = false;
212+
try {
213+
em.persist( new Book( "The Book of Foo", 1 ) );
214+
}
215+
catch ( PersistenceException e ) {
216+
caught = e.getCause().getClass().equals( HibernateException.class );
217+
}
218+
assertTrue( caught );
219+
220+
// Ensure that the connection was closed by the background thread.
221+
caught = false;
222+
try {
223+
em.createQuery( "from Book" ).getResultList();
224+
}
225+
catch ( PersistenceException e ) {
226+
caught = e.getCause().getClass().equals( GenericJDBCException.class );
227+
}
228+
assertTrue( caught );
229+
230+
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
215231
em.close();
216232
}
217233

0 commit comments

Comments
 (0)