/*
* 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.jdo;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.List;
import javax.jdo.JDOFatalDataStoreException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.beans.TestBean;
import org.springframework.jdbc.datasource.ConnectionHandle;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.SimpleConnectionHandle;
import org.springframework.transaction.InvalidIsolationLevelException;
import org.springframework.transaction.MockJtaTransaction;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
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
*/
public class JdoTransactionManagerTests extends TestCase {
private MockControl pmfControl, pmControl, txControl;
private PersistenceManagerFactory pmf;
private PersistenceManager pm;
private Transaction tx;
protected void setUp() {
pmfControl = MockControl.createControl(PersistenceManagerFactory.class);
pmf = (PersistenceManagerFactory) pmfControl.getMock();
pmControl = MockControl.createControl(PersistenceManager.class);
pm = (PersistenceManager) pmControl.getMock();
txControl = MockControl.createControl(Transaction.class);
tx = (Transaction) txControl.getMock();
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 1);
}
protected void tearDown() {
try {
pmfControl.verify();
pmControl.verify();
}
catch (IllegalStateException ex) {
// ignore: test method didn't call replay
}
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
}
public void testTransactionCommit() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.flush();
pmControl.setVoidCallable(2);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
TransactionAwarePersistenceManagerFactoryProxy proxyFactory =
new TransactionAwarePersistenceManagerFactoryProxy();
proxyFactory.setTargetPersistenceManagerFactory(pmf);
PersistenceManagerFactory proxy = (PersistenceManagerFactory) proxyFactory.getObject();
assertEquals(pm.toString(), proxy.getPersistenceManager().toString());
proxy.getPersistenceManager().flush();
proxy.getPersistenceManager().close();
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
public void testTransactionRollback() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 2);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
tx.isActive();
txControl.setReturnValue(true, 1);
tx.rollback();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
throw new RuntimeException("application exception");
}
});
}
});
fail("Should have thrown RuntimeException");
}
catch (RuntimeException ex) {
// expected
}
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
public void testTransactionRollbackWithAlreadyRolledBack() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 2);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
tx.isActive();
txControl.setReturnValue(false, 1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
throw new RuntimeException("application exception");
}
});
}
});
fail("Should have thrown RuntimeException");
}
catch (RuntimeException ex) {
// expected
}
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
public void testTransactionRollbackOnly() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 2);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
tx.isActive();
txControl.setReturnValue(true, 1);
tx.rollback();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return null;
}
});
status.setRollbackOnly();
return null;
}
});
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
}
public void testParticipatingTransactionWithCommit() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
final TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
txControl.reset();
tx.isActive();
txControl.setReturnValue(true, 1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
txControl.replay();
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
}
});
assertTrue("Correct result list", result == l);
}
public void testParticipatingTransactionWithRollback() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.close();
pmControl.setVoidCallable(1);
tx.isActive();
txControl.setReturnValue(false, 1);
tx.begin();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
final TransactionTemplate tt = new TransactionTemplate(tm);
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
txControl.reset();
tx.isActive();
txControl.setReturnValue(true, 3);
tx.setRollbackOnly();
txControl.setVoidCallable(1);
tx.rollback();
txControl.setVoidCallable(1);
txControl.replay();
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
throw new RuntimeException("application exception");
}
});
}
});
}
});
fail("Should have thrown RuntimeException");
}
catch (RuntimeException ex) {
// expected
}
}
public void testParticipatingTransactionWithRollbackOnly() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 5);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
tx.begin();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
final TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
try {
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
txControl.reset();
tx.isActive();
txControl.setReturnValue(true, 1);
tx.setRollbackOnly();
txControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(true, 1);
tx.commit();
txControl.setThrowable(new JDOFatalDataStoreException(), 1);
tx.isActive();
txControl.setReturnValue(false, 1);
txControl.replay();
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
status.setRollbackOnly();
return null;
}
});
}
});
fail("Should have thrown JdoResourceFailureException");
}
catch (JdoResourceFailureException ex) {
// expected
}
}
public void testParticipatingTransactionWithWithRequiresNew() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 2);
pm.currentTransaction();
pmControl.setReturnValue(tx, 6);
tx.begin();
txControl.setVoidCallable(1);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(2);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
final TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
final List l = new ArrayList();
l.add("test");
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
txControl.verify();
txControl.reset();
tx.isActive();
txControl.setReturnValue(true, 1);
tx.begin();
txControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 2);
tx.commit();
txControl.setVoidCallable(2);
txControl.replay();
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
}
});
assertTrue("Correct result list", result == l);
}
public void testParticipatingTransactionWithWithRequiresNewAndPrebound() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 3);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 6);
tx.begin();
txControl.setVoidCallable(1);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
final TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
txControl.verify();
txControl.reset();
tx.isActive();
txControl.setReturnValue(true, 1);
tx.begin();
txControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 2);
tx.commit();
txControl.setVoidCallable(2);
txControl.replay();
JdoTemplate jt = new JdoTemplate(pmf);
jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
return null;
}
});
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
TransactionSynchronizationManager.unbindResource(pmf);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
public void testJtaTransactionCommit() 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, 2);
ut.commit();
utControl.setVoidCallable(1);
utControl.replay();
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.flush();
pmControl.setVoidCallable(2);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut);
TransactionTemplate tt = new TransactionTemplate(ptm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("JTA synchronizations active", TransactionSynchronizationManager.isSynchronizationActive());
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
pm2.flush();
return l;
}
});
Object result = jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
pm2.flush();
return l;
}
});
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
return result;
}
});
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
}
public void testParticipatingJtaTransactionWithWithRequiresNewAndPrebound() throws Exception {
final MockControl utControl = MockControl.createControl(UserTransaction.class);
final UserTransaction ut = (UserTransaction) utControl.getMock();
final MockControl tmControl = MockControl.createControl(TransactionManager.class);
final TransactionManager tm = (TransactionManager) tmControl.getMock();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
ut.begin();
utControl.setVoidCallable(1);
utControl.replay();
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 1);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
JtaTransactionManager ptm = new JtaTransactionManager(ut, tm);
final TransactionTemplate tt = new TransactionTemplate(ptm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
utControl.verify();
utControl.reset();
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 1);
MockJtaTransaction transaction = new MockJtaTransaction();
tm.suspend();
tmControl.setReturnValue(transaction, 1);
ut.begin();
utControl.setVoidCallable(1);
ut.getStatus();
utControl.setReturnValue(Status.STATUS_ACTIVE, 4);
ut.commit();
utControl.setVoidCallable(2);
tm.resume(transaction);
tmControl.setVoidCallable(1);
utControl.replay();
tmControl.replay();
}
catch (Exception ex) {
}
JdoTemplate jt = new JdoTemplate(pmf);
jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
return null;
}
});
return tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
TransactionSynchronizationManager.unbindResource(pmf);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
utControl.verify();
}
public void testTransactionCommitWithPropagationSupports() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Is not new transaction", !status.isNewTransaction());
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
}
public void testInvalidIsolation() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 1);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(null, 1);
pm.close();
pmControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
try {
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
}
});
fail("Should have thrown InvalidIsolationLevelException");
}
catch (InvalidIsolationLevelException ex) {
// expected
}
}
public void testTransactionCommitWithPrebound() {
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
tx.isActive();
txControl.setReturnValue(false, 1);
tx.begin();
txControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
TransactionSynchronizationManager.bindResource(pmf, new PersistenceManagerHolder(pm));
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
TransactionSynchronizationManager.unbindResource(pmf);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
}
public void testTransactionCommitWithDataSource() throws SQLException {
MockControl dsControl = MockControl.createControl(DataSource.class);
final DataSource ds = (DataSource) dsControl.getMock();
MockControl dialectControl = MockControl.createControl(JdoDialect.class);
JdoDialect dialect = (JdoDialect) dialectControl.getMock();
MockControl conControl = MockControl.createControl(Connection.class);
final Connection con = (Connection) conControl.getMock();
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.close();
pmControl.setVoidCallable(1);
TransactionTemplate tt = new TransactionTemplate();
dialect.beginTransaction(tx, tt);
dialectControl.setReturnValue(null, 1);
dialect.getJdbcConnection(pm, false);
dialectControl.setReturnValue(conHandle, 1);
dialect.releaseJdbcConnection(conHandle, pm);
dialectControl.setVoidCallable(1);
dialect.cleanupTransaction(null);
dialectControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
dsControl.replay();
dialectControl.replay();
pmControl.replay();
txControl.replay();
conControl.replay();
JdoTransactionManager tm = new JdoTransactionManager();
tm.setPersistenceManagerFactory(pmf);
tm.setDataSource(ds);
tm.setJdoDialect(dialect);
tt.setTransactionManager(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
dsControl.verify();
dialectControl.verify();
conControl.verify();
}
public void testTransactionCommitWithAutoDetectedDataSource() throws SQLException {
MockControl dsControl = MockControl.createControl(DataSource.class);
final DataSource ds = (DataSource) dsControl.getMock();
MockControl dialectControl = MockControl.createControl(JdoDialect.class);
JdoDialect dialect = (JdoDialect) dialectControl.getMock();
MockControl conControl = MockControl.createControl(Connection.class);
final Connection con = (Connection) conControl.getMock();
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
pmfControl.reset();
pmf.getConnectionFactory();
pmfControl.setReturnValue(ds, 2);
con.getMetaData();
conControl.setReturnValue(null, 1);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.close();
pmControl.setVoidCallable(1);
TransactionTemplate tt = new TransactionTemplate();
dialect.beginTransaction(tx, tt);
dialectControl.setReturnValue(null, 1);
dialect.getJdbcConnection(pm, false);
dialectControl.setReturnValue(conHandle, 1);
dialect.releaseJdbcConnection(conHandle, pm);
dialectControl.setVoidCallable(1);
dialect.cleanupTransaction(null);
dialectControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
dsControl.replay();
dialectControl.replay();
pmControl.replay();
txControl.replay();
conControl.replay();
JdoTransactionManager tm = new JdoTransactionManager();
tm.setPersistenceManagerFactory(pmf);
tm.setJdoDialect(dialect);
tm.afterPropertiesSet();
tt.setTransactionManager(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) {
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
dsControl.verify();
dialectControl.verify();
conControl.verify();
}
public void testTransactionCommitWithAutoDetectedDataSourceAndNoConnection() throws SQLException {
MockControl dsControl = MockControl.createControl(DataSource.class);
final DataSource ds = (DataSource) dsControl.getMock();
MockControl dialectControl = MockControl.createControl(JdoDialect.class);
final JdoDialect dialect = (JdoDialect) dialectControl.getMock();
MockControl conControl = MockControl.createControl(Connection.class);
pmfControl.reset();
pmf.getConnectionFactory();
pmfControl.setReturnValue(ds, 1);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
TransactionTemplate tt = new TransactionTemplate();
dialect.beginTransaction(tx, tt);
dialectControl.setReturnValue(null, 1);
dialect.getJdbcConnection(pm, false);
dialectControl.setReturnValue(null, 1);
dialect.cleanupTransaction(null);
dialectControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
dsControl.replay();
dialectControl.replay();
pmControl.replay();
txControl.replay();
conControl.replay();
JdoTransactionManager tm = new JdoTransactionManager();
tm.setPersistenceManagerFactory(pmf);
tm.setJdoDialect(dialect);
tm.afterPropertiesSet();
tt.setTransactionManager(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
JdoTemplate jt = new JdoTemplate();
jt.setPersistenceManagerFactory(pmf);
jt.setJdoDialect(dialect);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
dsControl.verify();
dialectControl.verify();
conControl.verify();
}
public void testExistingTransactionWithPropagationNestedAndRollback() throws SQLException {
doTestExistingTransactionWithPropagationNestedAndRollback(false);
}
public void testExistingTransactionWithManualSavepointAndRollback() throws SQLException {
doTestExistingTransactionWithPropagationNestedAndRollback(true);
}
private void doTestExistingTransactionWithPropagationNestedAndRollback(final boolean manualSavepoint)
throws SQLException {
MockControl dsControl = MockControl.createControl(DataSource.class);
final DataSource ds = (DataSource) dsControl.getMock();
MockControl dialectControl = MockControl.createControl(JdoDialect.class);
JdoDialect dialect = (JdoDialect) dialectControl.getMock();
MockControl conControl = MockControl.createControl(Connection.class);
final Connection con = (Connection) conControl.getMock();
MockControl mdControl = MockControl.createControl(DatabaseMetaData.class);
DatabaseMetaData md = (DatabaseMetaData) mdControl.getMock();
MockControl spControl = MockControl.createControl(Savepoint.class);
Savepoint sp = (Savepoint) spControl.getMock();
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
pm.flush();
pmControl.setVoidCallable(1);
pm.close();
pmControl.setVoidCallable(1);
md.supportsSavepoints();
mdControl.setReturnValue(true, 1);
con.getMetaData();
conControl.setReturnValue(md, 1);
con.setSavepoint(ConnectionHolder.SAVEPOINT_NAME_PREFIX + 1);
conControl.setReturnValue(sp, 1);
con.rollback(sp);
conControl.setVoidCallable(1);
final TransactionTemplate tt = new TransactionTemplate();
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
dialect.beginTransaction(tx, tt);
dialectControl.setReturnValue(null, 1);
ConnectionHandle conHandle = new SimpleConnectionHandle(con);
dialect.getJdbcConnection(pm, false);
dialectControl.setReturnValue(conHandle, 1);
dialect.releaseJdbcConnection(conHandle, pm);
dialectControl.setVoidCallable(1);
dialect.cleanupTransaction(null);
dialectControl.setVoidCallable(1);
if (!manualSavepoint) {
tx.isActive();
txControl.setReturnValue(true, 1);
}
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
dsControl.replay();
dialectControl.replay();
pmControl.replay();
txControl.replay();
conControl.replay();
mdControl.replay();
spControl.replay();
JdoTransactionManager tm = new JdoTransactionManager();
tm.setNestedTransactionAllowed(true);
tm.setPersistenceManagerFactory(pmf);
tm.setDataSource(ds);
tm.setJdoDialect(dialect);
tt.setTransactionManager(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Has thread con", TransactionSynchronizationManager.hasResource(ds));
if (manualSavepoint) {
Object savepoint = status.createSavepoint();
status.rollbackToSavepoint(savepoint);
}
else {
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Has thread connection", TransactionSynchronizationManager.hasResource(ds));
status.setRollbackOnly();
}
});
}
JdoTemplate jt = new JdoTemplate(pmf);
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
pm2.flush();
return l;
}
});
}
});
assertTrue("Correct result list", result == l);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("Hasn't thread con", !TransactionSynchronizationManager.hasResource(ds));
dsControl.verify();
dialectControl.verify();
conControl.verify();
mdControl.verify();
spControl.verify();
}
public void testTransactionTimeoutWithJdoDialect() throws SQLException {
doTestTransactionTimeoutWithJdoDialect(true);
}
public void testTransactionTimeoutWithJdoDialectAndPmProxy() throws SQLException {
doTestTransactionTimeoutWithJdoDialect(false);
}
private void doTestTransactionTimeoutWithJdoDialect(final boolean exposeNativePm) throws SQLException {
MockControl queryControl = MockControl.createControl(Query.class);
Query query = (Query) queryControl.getMock();
MockControl dialectControl = MockControl.createControl(JdoDialect.class);
final JdoDialect dialect = (JdoDialect) dialectControl.getMock();
TransactionTemplate tt = new TransactionTemplate();
pmf.getConnectionFactory();
pmfControl.setReturnValue(null, 2);
pmf.getPersistenceManager();
pmfControl.setReturnValue(pm, 1);
pm.currentTransaction();
pmControl.setReturnValue(tx, 3);
dialect.beginTransaction(tx, tt);
dialectControl.setReturnValue(null, 1);
if (!exposeNativePm) {
dialect.applyQueryTimeout(query, 10);
}
dialect.cleanupTransaction(null);
dialectControl.setVoidCallable(1);
pm.newQuery(TestBean.class);
pmControl.setReturnValue(query, 1);
pm.close();
pmControl.setVoidCallable(1);
tx.getRollbackOnly();
txControl.setReturnValue(false, 1);
tx.commit();
txControl.setVoidCallable(1);
pmfControl.replay();
pmControl.replay();
txControl.replay();
queryControl.replay();
dialectControl.replay();
JdoTransactionManager tm = new JdoTransactionManager(pmf);
tm.setJdoDialect(dialect);
tt.setTransactionManager(tm);
tt.setTimeout(10);
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
JdoTemplate jt = new JdoTemplate(pmf);
jt.setJdoDialect(dialect);
if (exposeNativePm) {
jt.setExposeNativePersistenceManager(true);
}
return jt.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm2) {
if (exposeNativePm) {
assertSame(pm, pm2);
}
else {
assertTrue(Proxy.isProxyClass(pm2.getClass()));
}
pm2.newQuery(TestBean.class);
return null;
}
});
}
});
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
dialectControl.verify();
queryControl.verify();
}
}