/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.orm.hibernate3;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.springframework.dao.DataAccessException;
import org.springframework.transaction.MockJtaTransaction;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
/**
* @author Juergen Hoeller
* @since 05.03.2005
*/
public class HibernateJtaTransactionTests extends TestCase {
public void testJtaTransactionCommit() throws Exception {
doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, false);
}
public void testJtaTransactionCommitWithReadOnly() throws Exception {
doTestJtaTransactionCommit(Status.STATUS_NO_TRANSACTION, true);
}
public void testJtaTransactionCommitWithExisting() throws Exception {
doTestJtaTransactionCommit(Status.STATUS_ACTIVE, false);
}
public void testJtaTransactionCommitWithExistingAndReadOnly() throws Exception {
doTestJtaTransactionCommit(Status.STATUS_ACTIVE, true);
}
private void doTestJtaTransactionCommit(int status, final boolean readOnly) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
final MockControl queryControl = MockControl.createControl(Query.class);
Query query = (Query) queryControl.getMock();
ut.getStatus();
utControl.setReturnValue(status, 1);
if (status == Status.STATUS_NO_TRANSACTION) {
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.commit();
utControl.setVoidCallable(1);
}
else {
ut.getStatus();
utControl.setReturnValue(status, 1);
}
final List list = new ArrayList();
list.add("test");
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
session.isOpen();
sessionControl.setReturnValue(true, 1);
session.createQuery("some query string");
sessionControl.setReturnValue(query, 1);
if (readOnly) {
session.setFlushMode(FlushMode.NEVER);
sessionControl.setVoidCallable(1);
}
query.list();
queryControl.setReturnValue(list, 1);
utControl.replay();
sfControl.replay();
sessionControl.replay();
queryControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setReadOnly(readOnly);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
ht = new HibernateTemplate(sf);
List htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
return sess.createQuery("some query string").list();
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
sessionControl.verify();
queryControl.verify();
sessionControl.reset();
if (!readOnly) {
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
}
session.close();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
return htl;
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
assertTrue("Correct result list", result == list);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionCommitWithJtaTm() throws Exception {
doTestJtaTransactionCommitWithJtaTm(Status.STATUS_NO_TRANSACTION);
}
public void testJtaTransactionCommitWithJtaTmAndExisting() throws Exception {
doTestJtaTransactionCommitWithJtaTm(Status.STATUS_ACTIVE);
}
private void doTestJtaTransactionCommitWithJtaTm(int status) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(status, 2);
if (status == Status.STATUS_NO_TRANSACTION) {
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
ut.commit();
utControl.setVoidCallable(1);
}
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.getTransactionManager();
sfControl.setReturnValue(tm, 1);
sf.openSession();
sfControl.setReturnValue(session, 1);
session.isOpen();
sessionControl.setReturnValue(true, 1);
utControl.replay();
tmControl.replay();
sfControl.replay();
sessionControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
List htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return l;
}
});
ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return l;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
sessionControl.verify();
sessionControl.reset();
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
return htl;
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionWithFlushFailure() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
ut.rollback();
utControl.setVoidCallable(1);
utControl.replay();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
session.isOpen();
sessionControl.setReturnValue(true, 1);
sfControl.replay();
sessionControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
final List l = new ArrayList();
l.add("test");
final HibernateException flushEx = new HibernateException("flush failure");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
List htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return l;
}
});
ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return l;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
sessionControl.verify();
sessionControl.reset();
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setThrowable(flushEx);
session.close();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
return htl;
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
}
catch (DataAccessException ex) {
// expected
assertTrue(flushEx == ex.getCause());
}
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionRollback() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
ut.rollback();
utControl.setVoidCallable(1);
utControl.replay();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
sfControl.replay();
sessionControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
HibernateTemplate ht = new HibernateTemplate(sf);
List htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session session) {
return l;
}
});
status.setRollbackOnly();
sessionControl.verify();
sessionControl.reset();
session.close();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
return htl;
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
assertTrue("Correct result list", result == l);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionCommitWithPreBound() throws Exception {
doTestJtaTransactionCommitWithPreBound(false, false, false);
}
public void testJtaTransactionCommitWithPreBoundAndReadOnly() throws Exception {
doTestJtaTransactionCommitWithPreBound(false, false, true);
}
public void testJtaTransactionCommitWithPreBoundAndFlushModeNever() throws Exception {
doTestJtaTransactionCommitWithPreBound(false, true, false);
}
public void testJtaTransactionCommitWithPreBoundAndFlushModeNeverAndReadOnly() throws Exception {
doTestJtaTransactionCommitWithPreBound(false, true, true);
}
public void testJtaTransactionCommitWithJtaTmAndPreBound() throws Exception {
doTestJtaTransactionCommitWithPreBound(true, false, false);
}
public void testJtaTransactionCommitWithJtaTmAndPreBoundAndReadOnly() throws Exception {
doTestJtaTransactionCommitWithPreBound(true, false, true);
}
public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNever() throws Exception {
doTestJtaTransactionCommitWithPreBound(true, true, false);
}
public void testJtaTransactionCommitWithJtaTmAndPreBoundAndFlushModeNeverAndReadOnly() throws Exception {
doTestJtaTransactionCommitWithPreBound(true, true, true);
}
protected void doTestJtaTransactionCommitWithPreBound(
boolean jtaTm, final boolean flushNever, final boolean readOnly) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.begin();
utControl.setVoidCallable(1);
ut.commit();
utControl.setVoidCallable(1);
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
if (jtaTm) {
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 1);
}
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(ExtendedSession.class);
final ExtendedSession session = (ExtendedSession) sessionControl.getMock();
sf.getTransactionManager();
sfControl.setReturnValue((jtaTm ? tm : null), 1);
session.isOpen();
sessionControl.setReturnValue(true, 5);
session.getFlushMode();
if (flushNever) {
sessionControl.setReturnValue(FlushMode.NEVER, 1);
if (!readOnly) {
session.setFlushMode(FlushMode.AUTO);
sessionControl.setVoidCallable(1);
}
}
else {
sessionControl.setReturnValue(FlushMode.AUTO, 1);
}
utControl.replay();
tmControl.replay();
sfControl.replay();
sessionControl.replay();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
try {
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setReadOnly(readOnly);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
List htl = null;
for (int i = 0; i < 5; i++) {
htl = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return l;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
}
sessionControl.verify();
sessionControl.reset();
if (!readOnly) {
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
if (flushNever) {
session.setFlushMode(FlushMode.NEVER);
sessionControl.setVoidCallable(1);
}
}
session.afterTransactionCompletion(true, null);
sessionControl.setVoidCallable(1);
session.disconnect();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
return htl;
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
assertTrue("Correct result list", result == l);
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
finally {
TransactionSynchronizationManager.unbindResource(sf);
}
utControl.verify();
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionRollbackWithPreBound() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_MARKED_ROLLBACK, 2);
ut.begin();
utControl.setVoidCallable(1);
ut.setRollbackOnly();
utControl.setVoidCallable(1);
RollbackException rex = new RollbackException();
ut.commit();
utControl.setThrowable(rex, 1);
utControl.replay();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
session.isOpen();
sessionControl.setReturnValue(true, 5);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
sfControl.replay();
sessionControl.replay();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
try {
JtaTransactionManager ptm = new JtaTransactionManager(ut);
final TransactionTemplate tt = new TransactionTemplate(ptm);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
tt.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
status.setRollbackOnly();
try {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.execute(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
}
sessionControl.verify();
sessionControl.reset();
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.disconnect();
sessionControl.setReturnValue(null, 1);
session.clear();
sessionControl.setVoidCallable(1);
sessionControl.replay();
}
catch (Error err) {
err.printStackTrace();
throw err;
}
}
});
}
});
fail("Should have thrown UnexpectedRollbackException");
}
catch (UnexpectedRollbackException ex) {
// expected
assertEquals(rex, ex.getCause());
}
finally {
TransactionSynchronizationManager.unbindResource(sf);
}
utControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaTransactionCommitWithRequiresNew() throws Exception {
doTestJtaTransactionWithRequiresNew(false);
}
public void testJtaTransactionRollbackWithRequiresNew() throws Exception {
doTestJtaTransactionWithRequiresNew(true);
}
protected void doTestJtaTransactionWithRequiresNew(final boolean rollback) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction.class);
javax.transaction.Transaction tx1 = (javax.transaction.Transaction) tx1Control.getMock();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl session1Control = MockControl.createControl(Session.class);
final Session session1 = (Session) session1Control.getMock();
MockControl session2Control = MockControl.createControl(Session.class);
final Session session2 = (Session) session2Control.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
ut.begin();
utControl.setVoidCallable(2);
tm.suspend();
tmControl.setReturnValue(tx1, 1);
tm.resume(tx1);
tmControl.setVoidCallable(1);
if (rollback) {
ut.rollback();
}
else {
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.commit();
}
utControl.setVoidCallable(2);
sf.openSession();
sfControl.setReturnValue(session1, 1);
sf.openSession();
sfControl.setReturnValue(session2, 1);
session1.getSessionFactory();
session1Control.setReturnValue(sf, 1);
session2.getSessionFactory();
session2Control.setReturnValue(sf, 1);
session1.isOpen();
session1Control.setReturnValue(true, 1);
session2.isOpen();
session2Control.setReturnValue(true, 1);
session2.getFlushMode();
session2Control.setReturnValue(FlushMode.AUTO, 1);
if (!rollback) {
session1.getFlushMode();
session1Control.setReturnValue(FlushMode.AUTO, 1);
session2.getFlushMode();
session2Control.setReturnValue(FlushMode.AUTO, 1);
session1.flush();
session1Control.setVoidCallable(1);
session2.flush();
session2Control.setVoidCallable(2);
}
session1.disconnect();
session1Control.setReturnValue(null, 1);
session1.close();
session1Control.setReturnValue(null, 1);
session2.close();
session2Control.setReturnValue(null, 1);
utControl.replay();
tmControl.replay();
sfControl.replay();
session1Control.replay();
session2Control.replay();
JtaTransactionManager ptm = new JtaTransactionManager();
ptm.setUserTransaction(ut);
ptm.setTransactionManager(tm);
final TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
assertSame(session1, outerSession);
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Has thread session", holder != null);
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
org.hibernate.Session innerSession = SessionFactoryUtils.getSession(sf, false);
assertSame(session2, innerSession);
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
return ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session innerSession) {
if (rollback) {
throw new HibernateException("");
}
return null;
}
});
}
});
return null;
}
finally {
assertTrue("Same thread session as before", outerSession == SessionFactoryUtils.getSession(sf, false));
}
}
});
if (rollback) {
fail("Should have thrown DataAccessException");
}
}
catch (DataAccessException ex) {
if (!rollback) {
throw ex;
}
}
finally {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
}
utControl.verify();
tmControl.verify();
sfControl.verify();
session1Control.verify();
session2Control.verify();
}
public void testJtaTransactionWithRequiresNewAndSuspendException() throws Exception {
doTestJtaTransactionWithRequiresNewAndException(true);
}
public void testJtaTransactionWithRequiresNewAndBeginException() throws Exception {
doTestJtaTransactionWithRequiresNewAndException(false);
}
protected void doTestJtaTransactionWithRequiresNewAndException(boolean suspendException) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockControl txControl = MockControl.createControl(javax.transaction.Transaction.class);
javax.transaction.Transaction tx = (javax.transaction.Transaction) txControl.getMock();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl session1Control = MockControl.createControl(Session.class);
final Session session1 = (Session) session1Control.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.begin();
utControl.setVoidCallable(1);
if (suspendException) {
tm.suspend();
tmControl.setThrowable(new SystemException(), 1);
}
else {
tm.suspend();
tmControl.setReturnValue(tx, 1);
ut.begin();
utControl.setThrowable(new SystemException(), 1);
tm.resume(tx);
tmControl.setVoidCallable(1);
}
ut.rollback();
utControl.setVoidCallable(1);
sf.openSession();
sfControl.setReturnValue(session1, 1);
session1.getSessionFactory();
session1Control.setReturnValue(sf, 1);
session1.disconnect();
session1Control.setReturnValue(null, 1);
session1.close();
session1Control.setReturnValue(null, 1);
utControl.replay();
tmControl.replay();
sfControl.replay();
session1Control.replay();
JtaTransactionManager ptm = new JtaTransactionManager();
ptm.setUserTransaction(ut);
ptm.setTransactionManager(tm);
final TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
assertSame(session1, outerSession);
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Has thread session", holder != null);
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
return null;
}
});
return null;
}
});
fail("Should have thrown TransactionException");
}
catch (TransactionException ex) {
// expected
}
finally {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
}
utControl.verify();
tmControl.verify();
sfControl.verify();
session1Control.verify();
}
public void testJtaTransactionCommitWithRequiresNewAndJtaTm() throws Exception {
doTestJtaTransactionWithRequiresNewAndJtaTm(false);
}
public void testJtaTransactionRollbackWithRequiresNewAndJtaTm() throws Exception {
doTestJtaTransactionWithRequiresNewAndJtaTm(true);
}
protected void doTestJtaTransactionWithRequiresNewAndJtaTm(final boolean rollback) throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockControl tx1Control = MockControl.createControl(javax.transaction.Transaction.class);
javax.transaction.Transaction tx1 = (javax.transaction.Transaction) tx1Control.getMock();
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
MockControl session1Control = MockControl.createControl(Session.class);
final Session session1 = (Session) session1Control.getMock();
MockControl session2Control = MockControl.createControl(Session.class);
final Session session2 = (Session) session2Control.getMock();
MockJtaTransaction transaction1 = new MockJtaTransaction();
MockJtaTransaction transaction2 = new MockJtaTransaction();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 3);
ut.begin();
utControl.setVoidCallable(2);
tm.getTransaction();
tmControl.setReturnValue(transaction1, 1);
tm.suspend();
tmControl.setReturnValue(tx1, 1);
tm.getTransaction();
tmControl.setReturnValue(transaction2, 1);
tm.resume(tx1);
tmControl.setVoidCallable(1);
if (rollback) {
ut.rollback();
}
else {
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
ut.commit();
}
utControl.setVoidCallable(2);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 2);
sf.openSession();
sfControl.setReturnValue(session1, 1);
sf.openSession();
sfControl.setReturnValue(session2, 1);
session1.isOpen();
session1Control.setReturnValue(true, 1);
session2.isOpen();
session2Control.setReturnValue(true, 1);
session2.getFlushMode();
session2Control.setReturnValue(FlushMode.AUTO, 1);
if (!rollback) {
session1.getFlushMode();
session1Control.setReturnValue(FlushMode.AUTO, 1);
session2.getFlushMode();
session2Control.setReturnValue(FlushMode.AUTO, 1);
session1.flush();
session1Control.setVoidCallable(1);
session2.flush();
session2Control.setVoidCallable(2);
}
session1.disconnect();
session1Control.setReturnValue(null, 1);
session1.close();
session1Control.setReturnValue(null, 1);
session2.close();
session2Control.setReturnValue(null, 1);
utControl.replay();
tmControl.replay();
sfControl.replay();
session1Control.replay();
session2Control.replay();
JtaTransactionManager ptm = new JtaTransactionManager();
ptm.setUserTransaction(ut);
ptm.setTransactionManager(tm);
final TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
org.hibernate.Session outerSession = SessionFactoryUtils.getSession(sf, false);
assertSame(session1, outerSession);
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Has thread session", holder != null);
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
org.hibernate.Session innerSession = SessionFactoryUtils.getSession(sf, false);
assertSame(session2, innerSession);
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
return ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session innerSession) {
if (rollback) {
throw new HibernateException("");
}
return null;
}
});
}
});
return null;
}
finally {
assertTrue("Same thread session as before", outerSession == SessionFactoryUtils.getSession(sf, false));
}
}
});
if (rollback) {
fail("Should have thrown DataAccessException");
}
}
catch (DataAccessException ex) {
if (!rollback) {
throw ex;
}
}
finally {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
}
utControl.verify();
tmControl.verify();
sfControl.verify();
session1Control.verify();
session2Control.verify();
}
public void testTransactionWithPropagationSupports() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
ut.rollback();
utControl.setVoidCallable(1);
utControl.replay();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.NEVER, 1);
session.setFlushMode(FlushMode.AUTO);
sessionControl.setVoidCallable(1);
session.flush();
sessionControl.setVoidCallable(1);
session.setFlushMode(FlushMode.NEVER);
sessionControl.setVoidCallable(1);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.NEVER, 1);
session.close();
sessionControl.setReturnValue(null, 1);
sfControl.replay();
sessionControl.replay();
JtaTransactionManager tm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("Is not new transaction", !status.isNewTransaction());
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
ht.execute(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session session) {
return null;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
sfControl.verify();
sessionControl.verify();
}
public void testTransactionWithPropagationSupportsAndInnerTransaction() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
ut.rollback();
utControl.setVoidCallable(1);
utControl.replay();
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sf, 1);
session.isOpen();
sessionControl.setReturnValue(true, 1);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 3);
session.flush();
sessionControl.setVoidCallable(3);
session.close();
sessionControl.setReturnValue(null, 1);
sfControl.replay();
sessionControl.replay();
JtaTransactionManager tm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
final TransactionTemplate tt2 = new TransactionTemplate(tm);
tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("Is not new transaction", !status.isNewTransaction());
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
ht.execute(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session session) {
return null;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
tt2.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setFlushMode(HibernateTemplate.FLUSH_EAGER);
return ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session session) {
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
//assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
return null;
}
});
}
});
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronization() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
synchronization.beforeCompletion();
synchronization.afterCompletion(Status.STATUS_COMMITTED);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithRollback() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.close();
sessionControl.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithRollbackByOtherThread() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 7);
tm.getStatus();
tmControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 2);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 7);
session.isOpen();
sessionControl.setReturnValue(true, 8);
session.setFlushMode(FlushMode.NEVER);
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 2);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
final HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
final Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
Thread thread = new Thread() {
public void run() {
synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
}
};
thread.start();
thread.join();
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
TransactionTemplate tt = new TransactionTemplate(new JtaTransactionManager(tm));
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
tt.setReadOnly(true);
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithFlushFailure() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
tm.setRollbackOnly();
tmControl.setVoidCallable(1);
final HibernateException flushEx = new HibernateException("flush failure");
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setThrowable(flushEx, 1);
session.close();
sessionControl.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
try {
synchronization.beforeCompletion();
fail("Should have thrown HibernateSystemException");
}
catch (HibernateSystemException ex) {
assertSame(flushEx, ex.getCause());
}
synchronization.afterCompletion(Status.STATUS_ROLLEDBACK);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithSuspendedTransaction() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction1 = new MockJtaTransaction();
MockJtaTransaction transaction2 = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction1, 2);
tm.getTransaction();
tmControl.setReturnValue(transaction2, 3);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl session1Control = MockControl.createControl(Session.class);
final Session session1 = (Session) session1Control.getMock();
final MockControl session2Control = MockControl.createControl(Session.class);
final Session session2 = (Session) session2Control.getMock();
sf.openSession();
sfControl.setReturnValue(session1, 1);
sf.openSession();
sfControl.setReturnValue(session2, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 5);
session1.getFlushMode();
session1Control.setReturnValue(FlushMode.AUTO, 1);
session2.getFlushMode();
session2Control.setReturnValue(FlushMode.AUTO, 1);
session1.flush();
session1Control.setVoidCallable(1);
session2.flush();
session2Control.setVoidCallable(1);
session1.close();
session1Control.setReturnValue(null, 1);
session2.close();
session2Control.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
session1Control.replay();
session2Control.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session1, sess);
return null;
}
});
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session2, sess);
return null;
}
});
Synchronization synchronization2 = transaction2.getSynchronization();
assertTrue("JTA synchronization registered", synchronization2 != null);
synchronization2.beforeCompletion();
synchronization2.afterCompletion(Status.STATUS_COMMITTED);
Synchronization synchronization1 = transaction1.getSynchronization();
assertTrue("JTA synchronization registered", synchronization1 != null);
synchronization1.beforeCompletion();
synchronization1.afterCompletion(Status.STATUS_COMMITTED);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
session1Control.verify();
session2Control.verify();
}
public void testJtaSessionSynchronizationWithNonSessionFactoryImplementor() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl sfiControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sfi = (SessionFactoryImplementor) sfiControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
session.getSessionFactory();
sessionControl.setReturnValue(sfi, 6);
sfi.getTransactionManager();
sfiControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
sfiControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA Synchronization registered", synchronization != null);
synchronization.beforeCompletion();
synchronization.afterCompletion(Status.STATUS_COMMITTED);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
sfiControl.verify();
}
public void testJtaSessionSynchronizationWithSpringTransactionLaterOn() throws Exception {
MockControl utControl = MockControl.createControl(UserTransaction.class);
UserTransaction ut = (UserTransaction) utControl.getMock();
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 2);
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.openSession();
sfControl.setReturnValue(session, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 1);
utControl.replay();
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
final HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 2; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
TransactionTemplate tt = new TransactionTemplate(new JtaTransactionManager(ut));
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
for (int i = 2; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
}
});
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
synchronization.beforeCompletion();
synchronization.afterCompletion(Status.STATUS_COMMITTED);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithPreBound() throws Exception {
doTestJtaSessionSynchronizationWithPreBound(false);
}
public void testJtaJtaSessionSynchronizationWithPreBoundAndFlushNever() throws Exception {
doTestJtaSessionSynchronizationWithPreBound(true);
}
private void doTestJtaSessionSynchronizationWithPreBound(boolean flushNever) throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 5);
session.getFlushMode();
if (flushNever) {
sessionControl.setReturnValue(FlushMode.NEVER, 1);
session.setFlushMode(FlushMode.AUTO);
sessionControl.setVoidCallable(1);
}
else {
sessionControl.setReturnValue(FlushMode.AUTO, 1);
}
tmControl.replay();
sfControl.replay();
sessionControl.replay();
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session));
try {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
sessionControl.verify();
sessionControl.reset();
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
if (flushNever) {
session.setFlushMode(FlushMode.NEVER);
sessionControl.setVoidCallable(1);
}
session.disconnect();
sessionControl.setReturnValue(null, 1);
sessionControl.replay();
Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
synchronization.beforeCompletion();
synchronization.afterCompletion(Status.STATUS_COMMITTED);
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
}
finally {
TransactionSynchronizationManager.unbindResource(sf);
}
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
public void testJtaSessionSynchronizationWithRemoteTransaction() throws Exception {
MockControl tmControl = MockControl.createControl(TransactionManager.class);
TransactionManager tm = (TransactionManager) tmControl.getMock();
MockJtaTransaction transaction = new MockJtaTransaction();
MockControl sfControl = MockControl.createControl(SessionFactoryImplementor.class);
final SessionFactoryImplementor sf = (SessionFactoryImplementor) sfControl.getMock();
final MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
for (int j = 0; j < 2; j++) {
tmControl.reset();
sfControl.reset();
sessionControl.reset();
tm.getTransaction();
tmControl.setReturnValue(transaction, 6);
sf.openSession();
sfControl.setReturnValue(session, 1);
sf.getTransactionManager();
sfControl.setReturnValue(tm, 6);
session.isOpen();
sessionControl.setReturnValue(true, 4);
session.getFlushMode();
sessionControl.setReturnValue(FlushMode.AUTO, 1);
session.flush();
sessionControl.setVoidCallable(1);
session.close();
sessionControl.setReturnValue(null, 1);
tmControl.replay();
sfControl.replay();
sessionControl.replay();
if (j == 0) {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
}
else {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
}
HibernateTemplate ht = new HibernateTemplate(sf);
ht.setExposeNativeSession(true);
for (int i = 0; i < 5; i++) {
ht.executeFind(new HibernateCallback() {
public Object doInHibernate(org.hibernate.Session sess) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
assertEquals(session, sess);
return null;
}
});
}
final Synchronization synchronization = transaction.getSynchronization();
assertTrue("JTA synchronization registered", synchronization != null);
// Call synchronization in a new thread, to simulate a synchronization
// triggered by a new remote call from a remote transaction coordinator.
Thread synch = new Thread() {
public void run() {
synchronization.beforeCompletion();
synchronization.afterCompletion(Status.STATUS_COMMITTED);
}
};
synch.start();
synch.join();
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Thread session holder empty", sessionHolder.isEmpty());
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tmControl.verify();
sfControl.verify();
sessionControl.verify();
}
TransactionSynchronizationManager.unbindResource(sf);
}
protected void tearDown() {
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
}
/**
* Interface that combines Hibernate's Session and SessionImplementor interface.
* Necessary for creating a mock that implements both interfaces.
* Note: Hibernate 3.1's SessionImplementor interface does not extend Session anymore.
*/
public static interface ExtendedSession extends Session, SessionImplementor {
}
}