/*
* Created on Mar 20, 2005
*
*/
package org.springframework.orm.toplink;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import oracle.toplink.sessions.Session;
import oracle.toplink.sessions.UnitOfWork;
import org.easymock.MockControl;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
/**
* @author Juergen Hoeller
* @author <a href="mailto:james.x.clark@oracle.com">James Clark</a>
* @since 28.04.2005
*/
public class TopLinkTransactionManagerTests extends TestCase {
public void testTransactionCommit() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl uowControl = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow = (UnitOfWork) uowControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
// during commit, TM must get the active UnitOfWork
session.getActiveUnitOfWork();
sessionControl.setReturnValue(uow, 2);
uow.beginEarlyTransaction();
uowControl.setVoidCallable(1);
uow.commit();
uowControl.setVoidCallable();
// session should be released when it was bound explicitly by the TM
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
uowControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager();
tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
tm.setSessionFactory(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
tt.setTimeout(10);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
TopLinkTemplate template = new TopLinkTemplate(sf);
return template.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return null;
}
});
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sessionControl.verify();
uowControl.verify();
}
public void testTransactionRollback() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl uowControl = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow = (UnitOfWork) uowControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.getActiveUnitOfWork();
sessionControl.setReturnValue(uow, 1);
uow.beginEarlyTransaction();
uowControl.setVoidCallable(1);
session.release();
sessionControl.setVoidCallable(1);
sessionControl.replay();
uowControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager();
tm.setSessionFactory(sf);
tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
tt.setTimeout(10);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
try {
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
TopLinkTemplate template = new TopLinkTemplate(sf);
return template.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
throw new RuntimeException("failure");
}
});
}
});
fail("Should have propagated RuntimeException");
}
catch (RuntimeException ex) {
assertTrue(ex.getMessage().equals("failure"));
}
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sessionControl.verify();
uowControl.verify();
}
public void testTransactionRollbackOnly() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager();
tm.setSessionFactory(sf);
tm.setLazyDatabaseTransaction(true);
tm.setJdbcExceptionTranslator(new SQLStateSQLExceptionTranslator());
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
tt.setTimeout(10);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread session",
TransactionSynchronizationManager.hasResource(sf));
TopLinkTemplate template = new TopLinkTemplate(sf);
template.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return null;
}
});
status.setRollbackOnly();
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sessionControl.verify();
}
public void testParticipatingTransactionWithCommit() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl uowControl = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow = (UnitOfWork) uowControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.getActiveUnitOfWork();
sessionControl.setReturnValue(uow, 2);
uow.beginEarlyTransaction();
uowControl.setVoidCallable(1);
uow.commit();
uowControl.setVoidCallable();
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
uowControl.replay();
PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
final TransactionTemplate tt = new TransactionTemplate(tm);
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
TopLinkTemplate ht = new TopLinkTemplate(sf);
return ht.executeFind(new TopLinkCallback() {
public Object doInTopLink(Session injectedSession) {
assertTrue(session == injectedSession);
return null;
}
});
}
});
}
});
sessionControl.verify();
uowControl.verify();
}
public void testParticipatingTransactionWithRollback() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
tm.setLazyDatabaseTransaction(true);
final TransactionTemplate tt = new TransactionTemplate(tm);
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
TopLinkTemplate ht = new TopLinkTemplate(sf);
return ht.executeFind(new TopLinkCallback() {
public Object doInTopLink(Session session) {
throw new RuntimeException("application exception");
}
});
}
});
}
});
fail("Should not thrown RuntimeException");
}
catch (RuntimeException ex) {
assertTrue(ex.getMessage().equals("application exception"));
}
sessionControl.verify();
}
public void testParticipatingTransactionWithRollbackOnly() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
tm.setLazyDatabaseTransaction(true);
final TransactionTemplate tt = new TransactionTemplate(tm);
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
TopLinkTemplate ht = new TopLinkTemplate(sf);
ht.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return null;
}
});
status.setRollbackOnly();
return null;
}
});
return null;
}
});
fail("Should have thrown UnexpectedRollbackException");
}
catch (UnexpectedRollbackException ex) {
// expected
}
sessionControl.verify();
}
public void testParticipatingTransactionWithWithRequiresNew() {
MockControl session1Control = MockControl.createControl(Session.class);
final Session session1 = (Session) session1Control.getMock();
MockControl session2Control = MockControl.createControl(Session.class);
final Session session2 = (Session) session2Control.getMock();
MockControl uow1Control = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow1 = (UnitOfWork) uow1Control.getMock();
MockControl uow2Control = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow2 = (UnitOfWork) uow2Control.getMock();
final MockSessionFactory sf = new MockSessionFactory(session1);
session2.getActiveUnitOfWork();
session2Control.setReturnValue(uow2, 2);
uow2.beginEarlyTransaction();
uow2Control.setVoidCallable(1);
uow2.commit();
uow2Control.setVoidCallable();
session2.release();
session2Control.setVoidCallable();
session1.getActiveUnitOfWork();
session1Control.setReturnValue(uow1, 2);
uow1.beginEarlyTransaction();
uow1Control.setVoidCallable(1);
uow1.commit();
uow1Control.setVoidCallable();
session1.release();
session1Control.setVoidCallable();
session1Control.replay();
uow1Control.replay();
session2Control.replay();
uow2Control.replay();
PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
final TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
final SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Has thread session", holder != null);
sf.setSession(session2);
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
TopLinkTemplate ht = new TopLinkTemplate(sf);
return ht.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
assertTrue("Not enclosing session", session != holder.getSession());
return null;
}
});
}
});
assertTrue("Same thread session as before",
holder.getSession() == SessionFactoryUtils.getSession(sf, false));
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
session1Control.verify();
session2Control.verify();
uow1Control.verify();
uow2Control.verify();
}
public void testParticipatingTransactionWithWithNotSupported() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl uowControl = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow = (UnitOfWork) uowControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.getActiveUnitOfWork();
sessionControl.setReturnValue(uow, 2);
uow.beginEarlyTransaction();
uowControl.setVoidCallable(1);
uow.commit();
uowControl.setVoidCallable();
session.release();
sessionControl.setVoidCallable(2);
sessionControl.replay();
uowControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
final TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sf);
assertTrue("Has thread session", holder != null);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
TopLinkTemplate ht = new TopLinkTemplate(sf);
return ht.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return null;
}
});
}
});
assertTrue("Same thread session as before", holder.getSession() == SessionFactoryUtils.getSession(sf, false));
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
sessionControl.verify();
uowControl.verify();
}
public void testTransactionWithPropagationSupports() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
// not a new transaction, won't start a new one
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
PlatformTransactionManager tm = new TopLinkTransactionManager(sf);
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());
TopLinkTemplate ht = new TopLinkTemplate(sf);
ht.execute(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return null;
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
return null;
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
sessionControl.verify();
}
public void testTransactionCommitWithReadOnly() {
MockControl sessionControl = MockControl.createControl(Session.class);
final Session session = (Session) sessionControl.getMock();
MockControl uowControl = MockControl.createControl(UnitOfWork.class);
UnitOfWork uow = (UnitOfWork) uowControl.getMock();
final SessionFactory sf = new MockSessionFactory(session);
session.release();
sessionControl.setVoidCallable();
sessionControl.replay();
uowControl.replay();
TopLinkTransactionManager tm = new TopLinkTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setReadOnly(true);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
TopLinkTemplate ht = new TopLinkTemplate(sf);
return ht.executeFind(new TopLinkCallback() {
public Object doInTopLink(Session session) {
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sessionControl.verify();
uowControl.verify();
}
protected void tearDown() {
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
}
}