moving unit tests from .testsuite -> .transaction
fixed externals issue with .portlet that caused build failure
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class CallCountingTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
public TransactionDefinition lastDefinition;
|
||||
public int begun;
|
||||
public int commits;
|
||||
public int rollbacks;
|
||||
public int inflight;
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
this.lastDefinition = definition;
|
||||
++begun;
|
||||
++inflight;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
++commits;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
++rollbacks;
|
||||
--inflight;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
begun = commits = rollbacks = inflight = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.transaction.jta.UserTransactionAdapter;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 05.08.2005
|
||||
*/
|
||||
public class JndiJtaTransactionManagerTests extends TestCase {
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookups1() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:comp/TransactionManager", true, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookups2() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoTmFound() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/tm", false, true);
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithDefaultJndiLookupsAndNoUtFound() throws Exception {
|
||||
doTestJtaTransactionManagerWithDefaultJndiLookups("java:/TransactionManager", true, false);
|
||||
}
|
||||
|
||||
private void doTestJtaTransactionManagerWithDefaultJndiLookups(String tmName, boolean tmFound, boolean defaultUt)
|
||||
throws Exception {
|
||||
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
if (defaultUt) {
|
||||
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);
|
||||
}
|
||||
utControl.replay();
|
||||
|
||||
MockControl tmControl = MockControl.createControl(TransactionManager.class);
|
||||
TransactionManager tm = (TransactionManager) tmControl.getMock();
|
||||
if (!defaultUt) {
|
||||
tm.getStatus();
|
||||
tmControl.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
tm.getStatus();
|
||||
tmControl.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
tm.begin();
|
||||
tmControl.setVoidCallable(1);
|
||||
tm.commit();
|
||||
tmControl.setVoidCallable(1);
|
||||
}
|
||||
tmControl.replay();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
if (defaultUt) {
|
||||
jndiTemplate.addObject("java:comp/UserTransaction", ut);
|
||||
}
|
||||
jndiTemplate.addObject(tmName, tm);
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
if (tmFound) {
|
||||
assertEquals(tm, ptm.getTransactionManager());
|
||||
}
|
||||
else {
|
||||
assertNull(ptm.getTransactionManager());
|
||||
}
|
||||
|
||||
if (defaultUt) {
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
}
|
||||
else {
|
||||
assertTrue(ptm.getUserTransaction() instanceof UserTransactionAdapter);
|
||||
UserTransactionAdapter uta = (UserTransactionAdapter) ptm.getUserTransaction();
|
||||
assertEquals(tm, uta.getTransactionManager());
|
||||
}
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
tmControl.verify();
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithCustomJndiLookups() 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);
|
||||
utControl.replay();
|
||||
|
||||
MockControl tmControl = MockControl.createControl(TransactionManager.class);
|
||||
TransactionManager tm = (TransactionManager) tmControl.getMock();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ptm.setUserTransactionName("jndi-ut");
|
||||
ptm.setTransactionManagerName("jndi-tm");
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
jndiTemplate.addObject("jndi-ut", ut);
|
||||
jndiTemplate.addObject("jndi-tm", tm);
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
assertEquals(tm, ptm.getTransactionManager());
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
}
|
||||
|
||||
public void testJtaTransactionManagerWithNotCacheUserTransaction() 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);
|
||||
utControl.replay();
|
||||
|
||||
MockControl ut2Control = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut2 = (UserTransaction) ut2Control.getMock();
|
||||
ut2.getStatus();
|
||||
ut2Control.setReturnValue(Status.STATUS_NO_TRANSACTION, 1);
|
||||
ut2.getStatus();
|
||||
ut2Control.setReturnValue(Status.STATUS_ACTIVE, 2);
|
||||
ut2.begin();
|
||||
ut2Control.setVoidCallable(1);
|
||||
ut2.commit();
|
||||
ut2Control.setVoidCallable(1);
|
||||
ut2Control.replay();
|
||||
|
||||
JtaTransactionManager ptm = new JtaTransactionManager();
|
||||
ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut));
|
||||
ptm.setCacheUserTransaction(false);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
assertEquals(ut, ptm.getUserTransaction());
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(ptm);
|
||||
assertEquals(JtaTransactionManager.SYNCHRONIZATION_ALWAYS, ptm.getTransactionSynchronization());
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
|
||||
ptm.setJndiTemplate(new ExpectedLookupTemplate("java:comp/UserTransaction", ut2));
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
// something transactional
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
});
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
utControl.verify();
|
||||
ut2Control.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent any side-effects due to this test modifying ThreadLocals that might
|
||||
* affect subsequent tests when all tests are run in the same JVM, as with Eclipse.
|
||||
*/
|
||||
protected void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertNull(TransactionSynchronizationManager.getCurrentTransactionName());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.SimpleTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MockCallbackPreferringTransactionManager implements CallbackPreferringPlatformTransactionManager {
|
||||
|
||||
private TransactionDefinition definition;
|
||||
|
||||
private TransactionStatus status;
|
||||
|
||||
|
||||
public Object execute(TransactionDefinition definition, TransactionCallback callback) throws TransactionException {
|
||||
this.definition = definition;
|
||||
this.status = new SimpleTransactionStatus();
|
||||
return callback.doInTransaction(this.status);
|
||||
}
|
||||
|
||||
public TransactionDefinition getDefinition() {
|
||||
return this.definition;
|
||||
}
|
||||
|
||||
public TransactionStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction;
|
||||
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.xa.XAResource;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 31.08.2004
|
||||
*/
|
||||
public class MockJtaTransaction implements javax.transaction.Transaction {
|
||||
|
||||
private Synchronization synchronization;
|
||||
|
||||
public int getStatus() {
|
||||
return Status.STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
public void registerSynchronization(Synchronization synchronization) {
|
||||
this.synchronization = synchronization;
|
||||
}
|
||||
|
||||
public Synchronization getSynchronization() {
|
||||
return synchronization;
|
||||
}
|
||||
|
||||
public boolean enlistResource(XAResource xaResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean delistResource(XAResource xaResource, int i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
}
|
||||
|
||||
public void rollback() {
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction;
|
||||
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 29.04.2003
|
||||
*/
|
||||
class TestTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
private static final Object TRANSACTION = "transaction";
|
||||
|
||||
private final boolean existingTransaction;
|
||||
|
||||
private final boolean canCreateTransaction;
|
||||
|
||||
protected boolean begin = false;
|
||||
|
||||
protected boolean commit = false;
|
||||
|
||||
protected boolean rollback = false;
|
||||
|
||||
protected boolean rollbackOnly = false;
|
||||
|
||||
protected TestTransactionManager(boolean existingTransaction, boolean canCreateTransaction) {
|
||||
this.existingTransaction = existingTransaction;
|
||||
this.canCreateTransaction = canCreateTransaction;
|
||||
setTransactionSynchronization(SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
protected Object doGetTransaction() {
|
||||
return TRANSACTION;
|
||||
}
|
||||
|
||||
protected boolean isExistingTransaction(Object transaction) {
|
||||
return existingTransaction;
|
||||
}
|
||||
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
if (!TRANSACTION.equals(transaction)) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
if (!this.canCreateTransaction) {
|
||||
throw new CannotCreateTransactionException("Cannot create transaction");
|
||||
}
|
||||
this.begin = true;
|
||||
}
|
||||
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.commit = true;
|
||||
}
|
||||
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.rollback = true;
|
||||
}
|
||||
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
if (!TRANSACTION.equals(status.getTransaction())) {
|
||||
throw new IllegalArgumentException("Not the same transaction object");
|
||||
}
|
||||
this.rollbackOnly = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 29.04.2003
|
||||
*/
|
||||
public class TransactionSupportTests extends TestCase {
|
||||
|
||||
public void testNoExistingTransaction() {
|
||||
PlatformTransactionManager tm = new TestTransactionManager(false, true);
|
||||
DefaultTransactionStatus status1 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
assertTrue("Must not have transaction", status1.getTransaction() == null);
|
||||
|
||||
DefaultTransactionStatus status2 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
assertTrue("Must have transaction", status2.getTransaction() != null);
|
||||
assertTrue("Must be new transaction", status2.isNewTransaction());
|
||||
|
||||
try {
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
|
||||
fail("Should not have thrown NoTransactionException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistingTransaction() {
|
||||
PlatformTransactionManager tm = new TestTransactionManager(true, true);
|
||||
DefaultTransactionStatus status1 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
assertTrue("Must have transaction", status1.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status1.isNewTransaction());
|
||||
|
||||
DefaultTransactionStatus status2 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
assertTrue("Must have transaction", status2.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status2.isNewTransaction());
|
||||
|
||||
try {
|
||||
DefaultTransactionStatus status3 = (DefaultTransactionStatus)
|
||||
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY));
|
||||
assertTrue("Must have transaction", status3.getTransaction() != null);
|
||||
assertTrue("Must not be new transaction", !status3.isNewTransaction());
|
||||
}
|
||||
catch (NoTransactionException ex) {
|
||||
fail("Should not have thrown NoTransactionException");
|
||||
}
|
||||
}
|
||||
|
||||
public void testCommitWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.commit(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("triggered commit", tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.rollback(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackOnlyWithoutExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
status.setRollbackOnly();
|
||||
tm.commit(status);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testCommitWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.commit(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
tm.rollback(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("triggered rollbackOnly", tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testRollbackOnlyWithExistingTransaction() {
|
||||
TestTransactionManager tm = new TestTransactionManager(true, true);
|
||||
TransactionStatus status = tm.getTransaction(null);
|
||||
status.setRollbackOnly();
|
||||
tm.commit(status);
|
||||
assertTrue("no begin", !tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("triggered rollbackOnly", tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testTransactionTemplate() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
}
|
||||
});
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("triggered commit", tm.commit);
|
||||
assertTrue("no rollback", !tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithCallbackPreference() {
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
TransactionTemplate template = new TransactionTemplate(ptm);
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
}
|
||||
});
|
||||
assertSame(template, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithException() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
final RuntimeException ex = new RuntimeException("Some application exception");
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
}
|
||||
catch (RuntimeException caught) {
|
||||
// expected
|
||||
assertTrue("Correct exception", caught == ex);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithRollbackException() {
|
||||
final TransactionSystemException tex = new TransactionSystemException("system exception");
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true) {
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
super.doRollback(status);
|
||||
throw tex;
|
||||
}
|
||||
};
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
final RuntimeException ex = new RuntimeException("Some application exception");
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw ex;
|
||||
}
|
||||
});
|
||||
fail("Should have propagated RuntimeException");
|
||||
}
|
||||
catch (RuntimeException caught) {
|
||||
// expected
|
||||
assertTrue("Correct exception", caught == tex);
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateWithError() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate(tm);
|
||||
try {
|
||||
template.execute(new TransactionCallbackWithoutResult() {
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
throw new Error("Some application error");
|
||||
}
|
||||
});
|
||||
fail("Should have propagated Error");
|
||||
}
|
||||
catch (Error err) {
|
||||
// expected
|
||||
assertTrue("triggered begin", tm.begin);
|
||||
assertTrue("no commit", !tm.commit);
|
||||
assertTrue("triggered rollback", tm.rollback);
|
||||
assertTrue("no rollbackOnly", !tm.rollbackOnly);
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransactionTemplateInitialization() {
|
||||
TestTransactionManager tm = new TestTransactionManager(false, true);
|
||||
TransactionTemplate template = new TransactionTemplate();
|
||||
template.setTransactionManager(tm);
|
||||
assertTrue("correct transaction manager set", template.getTransactionManager() == tm);
|
||||
|
||||
try {
|
||||
template.setPropagationBehaviorName("TIMEOUT_DEFAULT");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setPropagationBehaviorName("PROPAGATION_SUPPORTS");
|
||||
assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
|
||||
try {
|
||||
template.setPropagationBehavior(999);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
assertTrue("Correct propagation behavior set", template.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
|
||||
try {
|
||||
template.setIsolationLevelName("TIMEOUT_DEFAULT");
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setIsolationLevelName("ISOLATION_SERIALIZABLE");
|
||||
assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_SERIALIZABLE);
|
||||
|
||||
try {
|
||||
template.setIsolationLevel(999);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
template.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertTrue("Correct isolation level set", template.getIsolationLevel() == TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CollectingReaderEventListener;
|
||||
import org.springframework.beans.factory.parsing.ComponentDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* @author Torsten Juergeleit
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class TxNamespaceHandlerEventTests extends TestCase {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
|
||||
|
||||
|
||||
public void setUp() throws Exception {
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
reader.setEventListener(this.eventListener);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("txNamespaceHandlerTests.xml", getClass()));
|
||||
}
|
||||
|
||||
public void testComponentEventReceived() {
|
||||
ComponentDefinition component = this.eventListener.getComponentDefinition("txAdvice");
|
||||
assertTrue(component instanceof BeanComponentDefinition);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.transaction;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
public class TxNamespaceHandlerTests extends TestCase {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
private Method getAgeMethod;
|
||||
|
||||
private Method setAgeMethod;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.context = new ClassPathXmlApplicationContext("txNamespaceHandlerTests.xml", getClass());
|
||||
this.getAgeMethod = ITestBean.class.getMethod("getAge", new Class[0]);
|
||||
this.setAgeMethod = ITestBean.class.getMethod("setAge", new Class[] {int.class});
|
||||
}
|
||||
|
||||
public void testIsProxy() throws Exception {
|
||||
ITestBean bean = getTestBean();
|
||||
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
}
|
||||
|
||||
public void testInvokeTransactional() throws Exception {
|
||||
ITestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
// try with transactional
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.getName();
|
||||
assertTrue(ptm.lastDefinition.isReadOnly());
|
||||
assertEquals("Should have 1 started transaction", 1, ptm.begun);
|
||||
assertEquals("Should have 1 committed transaction", 1, ptm.commits);
|
||||
|
||||
// try with non-transaction
|
||||
testBean.haveBirthday();
|
||||
assertEquals("Should not have started another transaction", 1, ptm.begun);
|
||||
|
||||
// try with exceptional
|
||||
try {
|
||||
testBean.exceptional(new IllegalArgumentException("foo"));
|
||||
fail("Should NEVER get here");
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
assertEquals("Should have another started transaction", 2, ptm.begun);
|
||||
assertEquals("Should have 1 rolled back transaction", 1, ptm.rollbacks);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRollbackRules() {
|
||||
TransactionInterceptor txInterceptor = (TransactionInterceptor) context.getBean("txRollbackAdvice");
|
||||
TransactionAttributeSource txAttrSource = txInterceptor.getTransactionAttributeSource();
|
||||
TransactionAttribute txAttr = txAttrSource.getTransactionAttribute(getAgeMethod,ITestBean.class);
|
||||
assertTrue("should be configured to rollback on Exception",txAttr.rollbackOn(new Exception()));
|
||||
|
||||
txAttr = txAttrSource.getTransactionAttribute(setAgeMethod, ITestBean.class);
|
||||
assertFalse("should not rollback on RuntimeException",txAttr.rollbackOn(new RuntimeException()));
|
||||
}
|
||||
|
||||
private ITestBean getTestBean() {
|
||||
return (ITestBean)context.getBean("testBean");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.transaction.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.interceptor.NoRollbackRuleAttribute;
|
||||
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
|
||||
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionAttributeSourceTests extends TestCase {
|
||||
|
||||
public void testSerializable() throws Exception {
|
||||
TestBean1 tb = new TestBean1();
|
||||
CallCountingTransactionManager ptm = new CallCountingTransactionManager();
|
||||
AnnotationTransactionAttributeSource tas = new AnnotationTransactionAttributeSource();
|
||||
TransactionInterceptor ti = new TransactionInterceptor(ptm, tas);
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
proxyFactory.addAdvice(ti);
|
||||
proxyFactory.setTarget(tb);
|
||||
ITestBean proxy = (ITestBean) proxyFactory.getProxy();
|
||||
proxy.getAge();
|
||||
assertEquals(1, ptm.commits);
|
||||
|
||||
ITestBean serializedProxy = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy);
|
||||
serializedProxy.getAge();
|
||||
Advised advised = (Advised) serializedProxy;
|
||||
TransactionInterceptor serializedTi = (TransactionInterceptor) advised.getAdvisors()[0].getAdvice();
|
||||
CallCountingTransactionManager serializedPtm =
|
||||
(CallCountingTransactionManager) serializedTi.getTransactionManager();
|
||||
assertEquals(2, serializedPtm.commits);
|
||||
}
|
||||
|
||||
public void testNullOrEmpty() throws Exception {
|
||||
Method method = Empty.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
assertNull(atas.getTransactionAttribute(method, null));
|
||||
|
||||
// Try again in case of caching
|
||||
assertNull(atas.getTransactionAttribute(method, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the important case where the invocation is on a proxied interface method
|
||||
* but the attribute is defined on the target class.
|
||||
*/
|
||||
public void testTransactionAttributeDeclaredOnClassMethod() throws Exception {
|
||||
Method classMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(classMethod, TestBean1.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case where attribute is on the interface method.
|
||||
*/
|
||||
public void testTransactionAttributeDeclaredOnInterfaceMethodOnly() throws Exception {
|
||||
Method interfaceMethod = ITestBean2.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(interfaceMethod, TestBean2.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that when an attribute exists on both class and interface, class takes precedence.
|
||||
*/
|
||||
public void testTransactionAttributeOnTargetClassMethodOverridesAttributeOnInterfaceMethod() throws Exception {
|
||||
Method interfaceMethod = ITestBean3.class.getMethod("getAge", (Class[]) null);
|
||||
Method interfaceMethod2 = ITestBean3.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(interfaceMethod, TestBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRES_NEW, actual.getPropagationBehavior());
|
||||
assertEquals(TransactionAttribute.ISOLATION_REPEATABLE_READ, actual.getIsolationLevel());
|
||||
assertEquals(5, actual.getTimeout());
|
||||
assertTrue(actual.isReadOnly());
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
|
||||
TransactionAttribute actual2 = atas.getTransactionAttribute(interfaceMethod2, TestBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, actual2.getPropagationBehavior());
|
||||
}
|
||||
|
||||
public void testRollbackRulesAreApplied() throws Exception {
|
||||
Method method = TestBean3.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean3.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
assertTrue(actual.rollbackOn(new Exception()));
|
||||
assertFalse(actual.rollbackOn(new IOException()));
|
||||
|
||||
actual = atas.getTransactionAttribute(method, method.getDeclaringClass());
|
||||
|
||||
rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
assertTrue(actual.rollbackOn(new Exception()));
|
||||
assertFalse(actual.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that transaction attribute is inherited from class
|
||||
* if not specified on method.
|
||||
*/
|
||||
public void testDefaultsToClassTransactionAttribute() throws Exception {
|
||||
Method method = TestBean4.class.getMethod("getAge", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute actual = atas.getTransactionAttribute(method, TestBean4.class);
|
||||
|
||||
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
|
||||
rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
|
||||
rbta.getRollbackRules().add(new NoRollbackRuleAttribute(IOException.class));
|
||||
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
|
||||
}
|
||||
|
||||
public void testTransactionAttributeDeclaredOnClassMethodWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean1.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean1.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
public void testTransactionAttributeDeclaredOnClassWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean2.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean2.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
public void testTransactionAttributeDeclaredOnInterfaceWithEjb3() throws Exception {
|
||||
Method getAgeMethod = ITestEjb.class.getMethod("getAge", (Class[]) null);
|
||||
Method getNameMethod = ITestEjb.class.getMethod("getName", (Class[]) null);
|
||||
|
||||
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
|
||||
TransactionAttribute getAgeAttr = atas.getTransactionAttribute(getAgeMethod, Ejb3AnnotatedBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_REQUIRED, getAgeAttr.getPropagationBehavior());
|
||||
TransactionAttribute getNameAttr = atas.getTransactionAttribute(getNameMethod, Ejb3AnnotatedBean3.class);
|
||||
assertEquals(TransactionAttribute.PROPAGATION_SUPPORTS, getNameAttr.getPropagationBehavior());
|
||||
}
|
||||
|
||||
|
||||
public interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public interface ITestBean2 {
|
||||
|
||||
@Transactional
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public interface ITestBean3 {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static class Empty implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public Empty() {
|
||||
}
|
||||
|
||||
public Empty(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean1 implements ITestBean, Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean1() {
|
||||
}
|
||||
|
||||
public TestBean1(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor=Exception.class)
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean2 implements ITestBean2 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean2() {
|
||||
}
|
||||
|
||||
public TestBean2(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean3 implements ITestBean3 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean3() {
|
||||
}
|
||||
|
||||
public TestBean3(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.REPEATABLE_READ, timeout=5,
|
||||
readOnly=true, rollbackFor=Exception.class, noRollbackFor={IOException.class})
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor=Exception.class, noRollbackFor={IOException.class})
|
||||
public static class TestBean4 implements ITestBean3 {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public TestBean4() {
|
||||
}
|
||||
|
||||
public TestBean4(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface Foo<T> {
|
||||
|
||||
void doSomething(T theArgument);
|
||||
}
|
||||
|
||||
|
||||
public static class MyFoo implements Foo<String> {
|
||||
|
||||
@Transactional
|
||||
public void doSomething(String theArgument) {
|
||||
System.out.println(theArgument);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Ejb3AnnotatedBean1 implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public static class Ejb3AnnotatedBean2 implements ITestBean {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@javax.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS)
|
||||
public interface ITestEjb {
|
||||
|
||||
@javax.ejb.TransactionAttribute
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
|
||||
public static class Ejb3AnnotatedBean3 implements ITestEjb {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.transaction.annotation;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionInterceptorTests extends TestCase {
|
||||
|
||||
private CallCountingTransactionManager ptm;
|
||||
|
||||
private AnnotationTransactionAttributeSource source;
|
||||
|
||||
private TransactionInterceptor ti;
|
||||
|
||||
|
||||
public void setUp() {
|
||||
this.ptm = new CallCountingTransactionManager();
|
||||
this.source = new AnnotationTransactionAttributeSource();
|
||||
this.ti = new TransactionInterceptor(this.ptm, this.source);
|
||||
}
|
||||
|
||||
|
||||
public void testClassLevelOnly() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestClassLevelOnly());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestClassLevelOnly proxy = (TestClassLevelOnly) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithSingleMethodOverride() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithSingleMethodOverride());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithSingleMethodOverride proxy = (TestWithSingleMethodOverride) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithSingleMethodOverrideInverted() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithSingleMethodOverrideInverted());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithSingleMethodOverrideInverted proxy = (TestWithSingleMethodOverrideInverted) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testWithMultiMethodOverride() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithMultiMethodOverride());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithMultiMethodOverride proxy = (TestWithMultiMethodOverride) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingCompletelyElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
|
||||
public void testWithRollback() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithRollback());
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithRollback proxy = (TestWithRollback) proxyFactory.getProxy();
|
||||
|
||||
try {
|
||||
proxy.doSomethingErroneous();
|
||||
fail("Should throw IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertGetTransactionAndRollbackCount(1);
|
||||
}
|
||||
|
||||
try {
|
||||
proxy.doSomethingElseErroneous();
|
||||
fail("Should throw IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertGetTransactionAndRollbackCount(2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testWithInterface() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new TestWithInterfaceImpl());
|
||||
proxyFactory.addInterface(TestWithInterface.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
TestWithInterface proxy = (TestWithInterface) proxyFactory.getProxy();
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
proxy.doSomethingElse();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
|
||||
proxy.doSomething();
|
||||
assertGetTransactionAndCommitCount(4);
|
||||
}
|
||||
|
||||
public void testCrossClassInterfaceMethodLevelOnJdkProxy() throws Exception {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new SomeServiceImpl());
|
||||
proxyFactory.addInterface(SomeService.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
SomeService someService = (SomeService) proxyFactory.getProxy();
|
||||
|
||||
someService.bar();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
|
||||
someService.foo();
|
||||
assertGetTransactionAndCommitCount(2);
|
||||
|
||||
someService.fooBar();
|
||||
assertGetTransactionAndCommitCount(3);
|
||||
}
|
||||
|
||||
public void testCrossClassInterfaceOnJdkProxy() throws Exception {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setTarget(new OtherServiceImpl());
|
||||
proxyFactory.addInterface(OtherService.class);
|
||||
proxyFactory.addAdvice(this.ti);
|
||||
|
||||
OtherService otherService = (OtherService) proxyFactory.getProxy();
|
||||
|
||||
otherService.foo();
|
||||
assertGetTransactionAndCommitCount(1);
|
||||
}
|
||||
|
||||
private void assertGetTransactionAndCommitCount(int expectedCount) {
|
||||
assertEquals(expectedCount, this.ptm.begun);
|
||||
assertEquals(expectedCount, this.ptm.commits);
|
||||
}
|
||||
|
||||
private void assertGetTransactionAndRollbackCount(int expectedCount) {
|
||||
assertEquals(expectedCount, this.ptm.begun);
|
||||
assertEquals(expectedCount, this.ptm.rollbacks);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestClassLevelOnly {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestWithSingleMethodOverride {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public static class TestWithSingleMethodOverrideInverted {
|
||||
|
||||
@Transactional
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class TestWithMultiMethodOverride {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingCompletelyElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = IllegalStateException.class)
|
||||
public static class TestWithRollback {
|
||||
|
||||
public void doSomethingErroneous() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = IllegalArgumentException.class)
|
||||
public void doSomethingElseErroneous() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static interface TestWithInterface {
|
||||
|
||||
public void doSomething();
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public void doSomethingElse();
|
||||
}
|
||||
|
||||
|
||||
public static class TestWithInterfaceImpl implements TestWithInterface {
|
||||
|
||||
public void doSomething() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
|
||||
public void doSomethingElse() {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface SomeService {
|
||||
|
||||
void foo();
|
||||
|
||||
@Transactional
|
||||
void bar();
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
void fooBar();
|
||||
}
|
||||
|
||||
|
||||
public static class SomeServiceImpl implements SomeService {
|
||||
|
||||
public void bar() {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void foo() {
|
||||
}
|
||||
|
||||
@Transactional(readOnly = false)
|
||||
public void fooBar() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static interface OtherService {
|
||||
|
||||
void foo();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public static class OtherServiceImpl implements OtherService {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.transaction.annotation;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationTransactionNamespaceHandlerTests extends TestCase {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
public void setUp() {
|
||||
this.context = new ClassPathXmlApplicationContext(
|
||||
"org/springframework/transaction/annotation/annotationTransactionNamespaceHandlerTests.xml");
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
public void testIsProxy() throws Exception {
|
||||
TransactionalTestBean bean = getTestBean();
|
||||
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
Map services = this.context.getBeansWithAnnotation(Service.class);
|
||||
assertTrue("Stereotype annotation not visible", services.containsKey("testBean"));
|
||||
}
|
||||
|
||||
public void testInvokeTransactional() throws Exception {
|
||||
TransactionalTestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
// try with transactional
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.findAllFoos();
|
||||
assertEquals("Should have 1 started transaction", 1, ptm.begun);
|
||||
assertEquals("Should have 1 committed transaction", 1, ptm.commits);
|
||||
|
||||
// try with non-transaction
|
||||
testBean.doSomething();
|
||||
assertEquals("Should not have started another transaction", 1, ptm.begun);
|
||||
|
||||
// try with exceptional
|
||||
try {
|
||||
testBean.exceptional(new IllegalArgumentException("foo"));
|
||||
fail("Should NEVER get here");
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
assertEquals("Should have another started transaction", 2, ptm.begun);
|
||||
assertEquals("Should have 1 rolled back transaction", 1, ptm.rollbacks);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testNonPublicMethodsNotAdvised() {
|
||||
TransactionalTestBean testBean = getTestBean();
|
||||
CallCountingTransactionManager ptm = (CallCountingTransactionManager) context.getBean("transactionManager");
|
||||
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
testBean.annotationsOnProtectedAreIgnored();
|
||||
assertEquals("Should not have any started transactions", 0, ptm.begun);
|
||||
}
|
||||
|
||||
public void testMBeanExportAlsoWorks() throws Exception {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
assertEquals("done",
|
||||
server.invoke(ObjectName.getInstance("test:type=TestBean"), "doSomething", new Object[0], new String[0]));
|
||||
}
|
||||
|
||||
private TransactionalTestBean getTestBean() {
|
||||
return (TransactionalTestBean) context.getBean("testBean");
|
||||
}
|
||||
|
||||
|
||||
@Service
|
||||
@ManagedResource("test:type=TestBean")
|
||||
public static class TransactionalTestBean {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Collection findAllFoos() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveFoo() {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
throw t;
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public String doSomething() {
|
||||
return "done";
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void annotationsOnProtectedAreIgnored() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<tx:annotation-driven/>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="testBean"
|
||||
class="org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests$TransactionalTestBean"/>
|
||||
|
||||
<context:mbean-export/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.transaction.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AnnotationDrivenTests extends TestCase {
|
||||
|
||||
public void testWithProxyTargetClass() throws Exception {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("annotationDrivenProxyTargetClassTests.xml", getClass());
|
||||
TransactionalService service = (TransactionalService) context.getBean("service");
|
||||
assertTrue(AopUtils.isCglibProxy(service));
|
||||
service.setBeanName("someName");
|
||||
}
|
||||
|
||||
|
||||
public static class TransactionCheckingInterceptor implements MethodInterceptor {
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.transaction.config;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@Transactional
|
||||
public class TransactionalService implements BeanNameAware {
|
||||
|
||||
public void setBeanName(String name) {
|
||||
// just for testing :)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
|
||||
|
||||
<tx:annotation-driven proxy-target-class="true" order="0"/>
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor advice-ref="txCheckingInterceptor" pointcut="execution(* *..TransactionalService.*(..))" order="1"/>
|
||||
</aop:config>
|
||||
|
||||
<bean id="txCheckingInterceptor" class="org.springframework.transaction.config.AnnotationDrivenTests$TransactionCheckingInterceptor"/>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="service" class="org.springframework.transaction.config.TransactionalService"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* 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.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.MockCallbackPreferringTransactionManager;
|
||||
import org.springframework.transaction.NoTransactionException;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.UnexpectedRollbackException;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo;
|
||||
|
||||
/**
|
||||
* Mock object based tests for transaction aspects.
|
||||
* True unit test in that it tests how the transaction aspect uses
|
||||
* the PlatformTransactionManager helper, rather than indirectly
|
||||
* testing the helper implementation.
|
||||
*
|
||||
* This is a superclass to allow testing both the AOP Alliance MethodInterceptor
|
||||
* and the AspectJ aspect.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 16.03.2003
|
||||
*/
|
||||
public abstract class AbstractTransactionAspectTests extends TestCase {
|
||||
|
||||
protected Method exceptionalMethod;
|
||||
|
||||
protected Method getNameMethod;
|
||||
|
||||
protected Method setNameMethod;
|
||||
|
||||
|
||||
public AbstractTransactionAspectTests() {
|
||||
try {
|
||||
// Cache the methods we'll be testing
|
||||
exceptionalMethod = ITestBean.class.getMethod("exceptional", new Class[] { Throwable.class });
|
||||
getNameMethod = ITestBean.class.getMethod("getName", (Class[]) null);
|
||||
setNameMethod = ITestBean.class.getMethod("setName", new Class[] { String.class} );
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException("Shouldn't happen", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testNoTransaction() throws Exception {
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
// expect no calls
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
TransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
|
||||
// All the methods in this class use the advised() template method
|
||||
// to obtain a transaction object, configured with the given PlatformTransactionManager
|
||||
// and transaction attribute source
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed.
|
||||
*/
|
||||
public void testTransactionShouldSucceed() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed using
|
||||
* CallbackPreferringPlatformTransactionManager.
|
||||
*/
|
||||
public void testTransactionShouldSucceedWithCallbackPreference() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
assertSame(txatt, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
public void testTransactionExceptionPropagatedWithCallbackPreference() throws Throwable {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(exceptionalMethod, txatt);
|
||||
|
||||
MockCallbackPreferringTransactionManager ptm = new MockCallbackPreferringTransactionManager();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
try {
|
||||
itb.exceptional(new OptimisticLockingFailureException(""));
|
||||
fail("Should have thrown OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException ex) {
|
||||
// expected
|
||||
}
|
||||
checkTransactionStatus(false);
|
||||
|
||||
assertSame(txatt, ptm.getDefinition());
|
||||
assertFalse(ptm.getStatus().isRollbackOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that two transactions are created and committed.
|
||||
*/
|
||||
public void testTwoTransactionsShouldSucceed() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas1 = new MapTransactionAttributeSource();
|
||||
tas1.register(getNameMethod, txatt);
|
||||
MapTransactionAttributeSource tas2 = new MapTransactionAttributeSource();
|
||||
tas2.register(setNameMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 2);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(2);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, new TransactionAttributeSource[] {tas1, tas2});
|
||||
|
||||
checkTransactionStatus(false);
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
itb.setName("myName");
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a transaction is created and committed.
|
||||
*/
|
||||
public void testTransactionShouldSucceedWithNotNew() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(getNameMethod, txatt);
|
||||
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
TransactionStatus status = (TransactionStatus) statusControl.getMock();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
// verification!?
|
||||
itb.getName();
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testEnclosingTransactionWithNonTransactionMethodOnAdvisedInside() throws Throwable {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(exceptionalMethod, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String spouseName = "innerName";
|
||||
|
||||
TestBean outer = new TestBean() {
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(spouseName, getSpouse().getName());
|
||||
}
|
||||
};
|
||||
TestBean inner = new TestBean() {
|
||||
public String getName() {
|
||||
// Assert that we're in the inner proxy
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertFalse(ti.hasTransaction());
|
||||
return spouseName;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
|
||||
ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
|
||||
outer.setSpouse(innerProxy);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
// Will invoke inner.getName, which is non-transactional
|
||||
outerProxy.exceptional(null);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testEnclosingTransactionWithNestedTransactionOnAdvisedInside() throws Throwable {
|
||||
final TransactionAttribute outerTxatt = new DefaultTransactionAttribute();
|
||||
final TransactionAttribute innerTxatt = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NESTED);
|
||||
|
||||
Method outerMethod = exceptionalMethod;
|
||||
Method innerMethod = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(outerMethod, outerTxatt);
|
||||
tas.register(innerMethod, innerTxatt);
|
||||
|
||||
TransactionStatus outerStatus = transactionStatusForNewTransaction();
|
||||
TransactionStatus innerStatus = transactionStatusForNewTransaction();
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(outerTxatt);
|
||||
ptmControl.setReturnValue(outerStatus, 1);
|
||||
|
||||
ptm.getTransaction(innerTxatt);
|
||||
ptmControl.setReturnValue(innerStatus, 1);
|
||||
|
||||
ptm.commit(innerStatus);
|
||||
ptmControl.setVoidCallable(1);
|
||||
|
||||
ptm.commit(outerStatus);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String spouseName = "innerName";
|
||||
|
||||
TestBean outer = new TestBean() {
|
||||
public void exceptional(Throwable t) throws Throwable {
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(outerTxatt, ti.getTransactionAttribute());
|
||||
assertEquals(spouseName, getSpouse().getName());
|
||||
}
|
||||
};
|
||||
TestBean inner = new TestBean() {
|
||||
public String getName() {
|
||||
// Assert that we're in the inner proxy
|
||||
TransactionInfo ti = TransactionAspectSupport.currentTransactionInfo();
|
||||
// Has nested transaction
|
||||
assertTrue(ti.hasTransaction());
|
||||
assertEquals(innerTxatt, ti.getTransactionAttribute());
|
||||
return spouseName;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean outerProxy = (ITestBean) advised(outer, ptm, tas);
|
||||
ITestBean innerProxy = (ITestBean) advised(inner, ptm, tas);
|
||||
outer.setSpouse(innerProxy);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
// Will invoke inner.getName, which is non-transactional
|
||||
outerProxy.exceptional(null);
|
||||
|
||||
checkTransactionStatus(false);
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testRollbackOnCheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), true, false);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnCheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), false, false);
|
||||
}
|
||||
|
||||
public void testRollbackOnUncheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), true, false);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnUncheckedException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), false, false);
|
||||
}
|
||||
|
||||
public void testRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), true, true);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnCheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new Exception(), false, true);
|
||||
}
|
||||
|
||||
public void testRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), true, true);
|
||||
}
|
||||
|
||||
public void testNoRollbackOnUncheckedExceptionWithRollbackException() throws Throwable {
|
||||
doTestRollbackOnException(new RuntimeException(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given exception thrown by the target can produce the
|
||||
* desired behavior with the appropriate transaction attribute.
|
||||
* @param ex exception to be thrown by the target
|
||||
* @param shouldRollback whether this should cause a transaction rollback
|
||||
*/
|
||||
protected void doTestRollbackOnException(
|
||||
final Exception ex, final boolean shouldRollback, boolean rollbackException) throws Exception {
|
||||
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute() {
|
||||
public boolean rollbackOn(Throwable t) {
|
||||
assertTrue(t == ex);
|
||||
return shouldRollback;
|
||||
}
|
||||
};
|
||||
|
||||
Method m = exceptionalMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
TransactionStatus status = (TransactionStatus) statusControl.getMock();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Gets additional call(s) from TransactionControl
|
||||
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
|
||||
if (shouldRollback) {
|
||||
ptm.rollback(status);
|
||||
}
|
||||
else {
|
||||
ptm.commit(status);
|
||||
}
|
||||
TransactionSystemException tex = new TransactionSystemException("system exception");
|
||||
if (rollbackException) {
|
||||
ptmControl.setThrowable(tex, 1);
|
||||
}
|
||||
else {
|
||||
ptmControl.setVoidCallable(1);
|
||||
}
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
try {
|
||||
itb.exceptional(ex);
|
||||
fail("Should have thrown exception");
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (rollbackException) {
|
||||
assertEquals("Caught wrong exception", tex, t );
|
||||
}
|
||||
else {
|
||||
assertEquals("Caught wrong exception", ex, t);
|
||||
}
|
||||
}
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that TransactionStatus.setRollbackOnly works.
|
||||
*/
|
||||
public void testProgrammaticRollback() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status, 1);
|
||||
ptm.commit(status);
|
||||
ptmControl.setVoidCallable(1);
|
||||
ptmControl.replay();
|
||||
|
||||
final String name = "jenny";
|
||||
TestBean tb = new TestBean() {
|
||||
public String getName() {
|
||||
TransactionStatus txStatus = TransactionInterceptor.currentTransactionStatus();
|
||||
txStatus.setRollbackOnly();
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
// verification!?
|
||||
assertTrue(name.equals(itb.getName()));
|
||||
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a TransactionStatus object configured for a new transaction
|
||||
*/
|
||||
private TransactionStatus transactionStatusForNewTransaction() {
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
return (TransactionStatus) statusControl.getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate a transaction infrastructure failure.
|
||||
* Shouldn't invoke target method.
|
||||
*/
|
||||
public void testCannotCreateTransaction() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = getNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect a transaction
|
||||
ptm.getTransaction(txatt);
|
||||
CannotCreateTransactionException ex = new CannotCreateTransactionException("foobar", null);
|
||||
ptmControl.setThrowable(ex);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean() {
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException(
|
||||
"Shouldn't have invoked target method when couldn't create transaction for transactional method");
|
||||
}
|
||||
};
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
try {
|
||||
itb.getName();
|
||||
fail("Shouldn't have invoked method");
|
||||
}
|
||||
catch (CannotCreateTransactionException thrown) {
|
||||
assertTrue(thrown == ex);
|
||||
}
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate failure of the underlying transaction infrastructure to commit.
|
||||
* Check that the target method was invoked, but that the transaction
|
||||
* infrastructure exception was thrown to the client
|
||||
*/
|
||||
public void testCannotCommitTransaction() throws Exception {
|
||||
TransactionAttribute txatt = new DefaultTransactionAttribute();
|
||||
|
||||
Method m = setNameMethod;
|
||||
MapTransactionAttributeSource tas = new MapTransactionAttributeSource();
|
||||
tas.register(m, txatt);
|
||||
Method m2 = getNameMethod;
|
||||
// No attributes for m2
|
||||
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
|
||||
TransactionStatus status = transactionStatusForNewTransaction();
|
||||
ptm.getTransaction(txatt);
|
||||
ptmControl.setReturnValue(status);
|
||||
UnexpectedRollbackException ex = new UnexpectedRollbackException("foobar", null);
|
||||
ptm.commit(status);
|
||||
ptmControl.setThrowable(ex);
|
||||
ptmControl.replay();
|
||||
|
||||
TestBean tb = new TestBean();
|
||||
ITestBean itb = (ITestBean) advised(tb, ptm, tas);
|
||||
|
||||
String name = "new name";
|
||||
try {
|
||||
itb.setName(name);
|
||||
fail("Shouldn't have succeeded");
|
||||
}
|
||||
catch (UnexpectedRollbackException thrown) {
|
||||
assertTrue(thrown == ex);
|
||||
}
|
||||
|
||||
// Should have invoked target and changed name
|
||||
assertTrue(itb.getName() == name);
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
protected void checkTransactionStatus(boolean expected) {
|
||||
try {
|
||||
TransactionInterceptor.currentTransactionStatus();
|
||||
if (!expected) {
|
||||
fail("Should have thrown NoTransactionException");
|
||||
}
|
||||
}
|
||||
catch (NoTransactionException ex) {
|
||||
if (expected) {
|
||||
fail("Should have current TransactionStatus");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Object advised(
|
||||
Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
|
||||
|
||||
return advised(target, ptm, new CompositeTransactionAttributeSource(tas));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this to create an advised object based on the
|
||||
* given target. In the case of AspectJ, the advised object will already
|
||||
* have been created, as there's no distinction between target and proxy.
|
||||
* In the case of Spring's own AOP framework, a proxy must be created
|
||||
* using a suitably configured transaction interceptor
|
||||
* @param target target if there's a distinct target. If not (AspectJ),
|
||||
* return target.
|
||||
* @return transactional advised object
|
||||
*/
|
||||
protected abstract Object advised(
|
||||
Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcut;
|
||||
import org.springframework.aop.target.HotSwappableTargetSource;
|
||||
import org.springframework.beans.DerivedTestBean;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.xml.XmlBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
/**
|
||||
* Test cases for AOP transaction management.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 23.04.2003
|
||||
*/
|
||||
public class BeanFactoryTransactionTests extends TestCase {
|
||||
|
||||
private XmlBeanFactory factory;
|
||||
|
||||
public void setUp() {
|
||||
this.factory = new XmlBeanFactory(new ClassPathResource("transactionalBeanFactory.xml", getClass()));
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory1() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory1");
|
||||
assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
|
||||
doTestGetsAreNotTransactional(testBean, ITestBean.class);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory2DynamicProxy() throws NoSuchMethodException {
|
||||
this.factory.preInstantiateSingletons();
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2DynamicProxy");
|
||||
assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass()));
|
||||
doTestGetsAreNotTransactional(testBean, ITestBean.class);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory2Cglib() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Cglib");
|
||||
assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(testBean));
|
||||
doTestGetsAreNotTransactional(testBean, TestBean.class);
|
||||
}
|
||||
|
||||
public void testProxyFactory2Lazy() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Lazy");
|
||||
assertFalse(factory.containsSingleton("target"));
|
||||
assertEquals(666, testBean.getAge());
|
||||
assertTrue(factory.containsSingleton("target"));
|
||||
}
|
||||
|
||||
public void testCglibTransactionProxyImplementsNoInterfaces() throws NoSuchMethodException {
|
||||
ImplementsNoInterfaces ini = (ImplementsNoInterfaces) factory.getBean("cglibNoInterfaces");
|
||||
assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(ini));
|
||||
String newName = "Gordon";
|
||||
|
||||
// Install facade
|
||||
CallCountingTransactionManager ptm = new CallCountingTransactionManager();
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
ini.setName(newName);
|
||||
assertEquals(newName, ini.getName());
|
||||
assertEquals(2, ptm.commits);
|
||||
}
|
||||
|
||||
public void testGetsAreNotTransactionalWithProxyFactory3() throws NoSuchMethodException {
|
||||
ITestBean testBean = (ITestBean) factory.getBean("proxyFactory3");
|
||||
assertTrue("testBean is a full proxy", testBean instanceof DerivedTestBean);
|
||||
InvocationCounterPointcut txnCounter = (InvocationCounterPointcut) factory.getBean("txnInvocationCounterPointcut");
|
||||
InvocationCounterInterceptor preCounter = (InvocationCounterInterceptor) factory.getBean("preInvocationCounterInterceptor");
|
||||
InvocationCounterInterceptor postCounter = (InvocationCounterInterceptor) factory.getBean("postInvocationCounterInterceptor");
|
||||
txnCounter.counter = 0;
|
||||
preCounter.counter = 0;
|
||||
postCounter.counter = 0;
|
||||
doTestGetsAreNotTransactional(testBean, TestBean.class);
|
||||
// Can't assert it's equal to 4 as the pointcut may be optimized and only invoked once
|
||||
assertTrue(0 < txnCounter.counter && txnCounter.counter <= 4);
|
||||
assertEquals(4, preCounter.counter);
|
||||
assertEquals(4, postCounter.counter);
|
||||
}
|
||||
|
||||
private void doTestGetsAreNotTransactional(final ITestBean testBean, final Class proxyClass) {
|
||||
// Install facade
|
||||
MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class);
|
||||
PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock();
|
||||
// Expect no methods
|
||||
ptmControl.replay();
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
assertTrue("Age should not be " + testBean.getAge(), testBean.getAge() == 666);
|
||||
// Check no calls
|
||||
ptmControl.verify();
|
||||
|
||||
// Install facade expecting a call
|
||||
MockControl statusControl = MockControl.createControl(TransactionStatus.class);
|
||||
final TransactionStatus ts = (TransactionStatus) statusControl.getMock();
|
||||
ptm = new PlatformTransactionManager() {
|
||||
private boolean invoked;
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
if (invoked) {
|
||||
throw new IllegalStateException("getTransaction should not get invoked more than once");
|
||||
}
|
||||
invoked = true;
|
||||
if (!((definition.getName().indexOf(proxyClass.getName()) != -1) &&
|
||||
(definition.getName().indexOf("setAge") != -1))) {
|
||||
throw new IllegalStateException(
|
||||
"transaction name should contain class and method name: " + definition.getName());
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
assertTrue(status == ts);
|
||||
}
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new IllegalStateException("rollback should not get invoked");
|
||||
}
|
||||
};
|
||||
PlatformTransactionManagerFacade.delegate = ptm;
|
||||
|
||||
// TODO same as old age to avoid ordering effect for now
|
||||
int age = 666;
|
||||
testBean.setAge(age);
|
||||
assertTrue(testBean.getAge() == age);
|
||||
ptmControl.verify();
|
||||
}
|
||||
|
||||
public void testGetBeansOfTypeWithAbstract() {
|
||||
Map beansOfType = factory.getBeansOfType(ITestBean.class, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that we fail gracefully if the user doesn't set any transaction attributes.
|
||||
*/
|
||||
public void testNoTransactionAttributeSource() {
|
||||
try {
|
||||
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("noTransactionAttributeSource.xml", getClass()));
|
||||
ITestBean testBean = (ITestBean) bf.getBean("noTransactionAttributeSource");
|
||||
fail("Should require TransactionAttributeSource to be set");
|
||||
}
|
||||
catch (FatalBeanException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can set the target to a dynamic TargetSource.
|
||||
*/
|
||||
public void testDynamicTargetSource() throws NoSuchMethodException {
|
||||
// Install facade
|
||||
CallCountingTransactionManager txMan = new CallCountingTransactionManager();
|
||||
PlatformTransactionManagerFacade.delegate = txMan;
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("hotSwapped");
|
||||
assertEquals(666, tb.getAge());
|
||||
int newAge = 557;
|
||||
tb.setAge(newAge);
|
||||
assertEquals(newAge, tb.getAge());
|
||||
|
||||
TestBean target2 = new TestBean();
|
||||
target2.setAge(65);
|
||||
HotSwappableTargetSource ts = (HotSwappableTargetSource) factory.getBean("swapper");
|
||||
ts.swap(target2);
|
||||
assertEquals(target2.getAge(), tb.getAge());
|
||||
tb.setAge(newAge);
|
||||
assertEquals(newAge, target2.getAge());
|
||||
|
||||
assertEquals(0, txMan.inflight);
|
||||
assertEquals(2, txMan.commits);
|
||||
assertEquals(0, txMan.rollbacks);
|
||||
}
|
||||
|
||||
|
||||
public static class InvocationCounterPointcut extends StaticMethodMatcherPointcut {
|
||||
|
||||
int counter = 0;
|
||||
|
||||
public boolean matches(Method method, Class clazz) {
|
||||
counter++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class InvocationCounterInterceptor implements MethodInterceptor {
|
||||
|
||||
int counter = 0;
|
||||
|
||||
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
|
||||
counter++;
|
||||
return methodInvocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import org.springframework.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Test for CGLIB proxying that implements no interfaces
|
||||
* and has one dependency.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class ImplementsNoInterfaces {
|
||||
|
||||
private TestBean testBean;
|
||||
|
||||
public void setDependency(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return testBean.getName();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
testBean.setName(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Inherits fallback behavior from AbstractFallbackTransactionAttributeSource.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MapTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource {
|
||||
|
||||
/** Map from Method or Clazz to TransactionAttribute */
|
||||
private final Map attributeMap = new HashMap();
|
||||
|
||||
public void register(Method m, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(m, txAtt);
|
||||
}
|
||||
|
||||
public void register(Class clazz, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(clazz, txAtt);
|
||||
}
|
||||
|
||||
|
||||
protected TransactionAttribute findTransactionAttribute(Method method) {
|
||||
return (TransactionAttribute) this.attributeMap.get(method);
|
||||
}
|
||||
|
||||
protected TransactionAttribute findTransactionAttribute(Class clazz) {
|
||||
return (TransactionAttribute) this.attributeMap.get(clazz);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.transaction.interceptor;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* An example {@link RuntimeException} for use in testing rollback rules.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class MyRuntimeException extends NestedRuntimeException {
|
||||
public MyRuntimeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
/**
|
||||
* Used for testing only (for example, when we must replace the
|
||||
* behavior of a PlatformTransactionManager bean we don't have access to).
|
||||
*
|
||||
* <p>Allows behavior of an entire class to change with static delegate change.
|
||||
* Not multi-threaded.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class PlatformTransactionManagerFacade implements PlatformTransactionManager {
|
||||
|
||||
/**
|
||||
* This member can be changed to change behavior class-wide.
|
||||
*/
|
||||
public static PlatformTransactionManager delegate;
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) {
|
||||
return delegate.getTransaction(definition);
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) {
|
||||
delegate.commit(status);
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) {
|
||||
delegate.rollback(status);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.transaction.interceptor;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link RollbackRuleAttribute} class.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 09.04.2003
|
||||
*/
|
||||
public class RollbackRuleTests extends TestCase {
|
||||
|
||||
public void testFoundImmediatelyWithString() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Exception.class.getName());
|
||||
assertTrue(rr.getDepth(new Exception()) == 0);
|
||||
}
|
||||
|
||||
public void testFoundImmediatelyWithClass() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(Exception.class);
|
||||
assertTrue(rr.getDepth(new Exception()) == 0);
|
||||
}
|
||||
|
||||
public void testNotFound() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.io.IOException.class.getName());
|
||||
assertTrue(rr.getDepth(new MyRuntimeException("")) == -1);
|
||||
}
|
||||
|
||||
public void testAncestry() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Exception.class.getName());
|
||||
// Exception -> Runtime -> NestedRuntime -> MyRuntimeException
|
||||
assertThat(rr.getDepth(new MyRuntimeException("")), equalTo(3));
|
||||
}
|
||||
|
||||
public void testAlwaysTrueForThrowable() {
|
||||
RollbackRuleAttribute rr = new RollbackRuleAttribute(java.lang.Throwable.class.getName());
|
||||
assertTrue(rr.getDepth(new MyRuntimeException("")) > 0);
|
||||
assertTrue(rr.getDepth(new IOException()) > 0);
|
||||
assertTrue(rr.getDepth(new FatalBeanException(null,null)) > 0);
|
||||
assertTrue(rr.getDepth(new RuntimeException()) > 0);
|
||||
}
|
||||
|
||||
public void testCtorArgMustBeAThrowableClassWithNonThrowableType() {
|
||||
try {
|
||||
new RollbackRuleAttribute(StringBuffer.class);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a non-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorArgMustBeAThrowableClassWithNullThrowableType() {
|
||||
try {
|
||||
new RollbackRuleAttribute((Class) null);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorArgExceptionStringNameVersionWithNull() {
|
||||
try {
|
||||
new RollbackRuleAttribute((String) null);
|
||||
fail("Cannot construct a RollbackRuleAttribute with a null-Throwable type");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.transaction.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 09.04.2003
|
||||
*/
|
||||
public class RuleBasedTransactionAttributeTests {
|
||||
|
||||
@Test
|
||||
public void testDefaultRule() {
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute();
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test one checked exception that should roll back.
|
||||
*/
|
||||
@Test
|
||||
public void testRuleForRollbackOnChecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new RollbackRuleAttribute(IOException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForCommitOnUnchecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute(MyRuntimeException.class.getName()));
|
||||
list.add(new RollbackRuleAttribute(IOException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
// Check default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForSelectiveRollbackOnCheckedWithString() {
|
||||
List<RollbackRuleAttribute> l = new LinkedList<RollbackRuleAttribute>();
|
||||
l.add(new RollbackRuleAttribute(java.rmi.RemoteException.class.getName()));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
|
||||
doTestRuleForSelectiveRollbackOnChecked(rta);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleForSelectiveRollbackOnCheckedWithClass() {
|
||||
List<RollbackRuleAttribute> l = Collections.singletonList(new RollbackRuleAttribute(RemoteException.class));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, l);
|
||||
doTestRuleForSelectiveRollbackOnChecked(rta);
|
||||
}
|
||||
|
||||
private void doTestRuleForSelectiveRollbackOnChecked(RuleBasedTransactionAttribute rta) {
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
// Check default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertTrue(rta.rollbackOn(new RemoteException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a rule can cause commit on a IOException
|
||||
* when Exception prompts a rollback.
|
||||
*/
|
||||
@Test
|
||||
public void testRuleForCommitOnSubclassOfChecked() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
// Note that it's important to ensure that we have this as
|
||||
// a FQN: otherwise it will match everything!
|
||||
list.add(new RollbackRuleAttribute("java.lang.Exception"));
|
||||
list.add(new NoRollbackRuleAttribute("IOException"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new RuntimeException()));
|
||||
assertTrue(rta.rollbackOn(new Exception()));
|
||||
// Check that default behaviour is overridden
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRollbackNever() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute("Throwable"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertFalse(rta.rollbackOn(new Throwable()));
|
||||
assertFalse(rta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringMatchesEditor() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute("Throwable"));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
TransactionAttributeEditor tae = new TransactionAttributeEditor();
|
||||
tae.setAsText(rta.toString());
|
||||
rta = (RuleBasedTransactionAttribute) tae.getValue();
|
||||
|
||||
assertFalse(rta.rollbackOn(new Throwable()));
|
||||
assertFalse(rta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(rta.rollbackOn(new MyRuntimeException("")));
|
||||
assertFalse(rta.rollbackOn(new Exception()));
|
||||
assertFalse(rta.rollbackOn(new IOException()));
|
||||
}
|
||||
|
||||
/**
|
||||
* See <a href="http://forum.springframework.org/showthread.php?t=41350">this forum post</a>.
|
||||
*/
|
||||
@Test
|
||||
public void testConflictingRulesToDetermineExactContract() {
|
||||
List<RollbackRuleAttribute> list = new LinkedList<RollbackRuleAttribute>();
|
||||
list.add(new NoRollbackRuleAttribute(MyBusinessWarningException.class));
|
||||
list.add(new RollbackRuleAttribute(MyBusinessException.class));
|
||||
RuleBasedTransactionAttribute rta = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, list);
|
||||
|
||||
assertTrue(rta.rollbackOn(new MyBusinessException()));
|
||||
assertFalse(rta.rollbackOn(new MyBusinessWarningException()));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class MyBusinessException extends Exception {}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static final class MyBusinessWarningException extends MyBusinessException {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Tests to check conversion from String to TransactionAttribute.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class TransactionAttributeEditorTests {
|
||||
|
||||
@Test
|
||||
public void testNull() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(null);
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyString() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeOnly() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_REQUIRED");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
|
||||
assertTrue(!ta.isReadOnly());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testInvalidPropagationCodeOnly() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
// should have failed with bogus propagation code
|
||||
pe.setAsText("XXPROPAGATION_REQUIRED");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCode() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_REQUIRED, ISOLATION_READ_UNCOMMITTED");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testValidPropagationAndIsolationCodesAndInvalidRollbackRule() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
// should fail with bogus rollback rule
|
||||
pe.setAsText("PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED,XXX");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCodeAndRollbackRules1() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("PROPAGATION_MANDATORY,ISOLATION_REPEATABLE_READ,timeout_10,-IOException,+MyRuntimeException");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertNotNull(ta);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertFalse(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
// Check for our bizarre customized rollback rules
|
||||
assertTrue(ta.rollbackOn(new IOException()));
|
||||
assertTrue(!ta.rollbackOn(new MyRuntimeException("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPropagationCodeAndIsolationCodeAndRollbackRules2() {
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText("+IOException,readOnly,ISOLATION_READ_COMMITTED,-MyRuntimeException,PROPAGATION_SUPPORTS");
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertNotNull(ta);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||
assertEquals(ta.getTimeout(), TransactionDefinition.TIMEOUT_DEFAULT);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
// Check for our bizarre customized rollback rules
|
||||
assertFalse(ta.rollbackOn(new IOException()));
|
||||
assertTrue(ta.rollbackOn(new MyRuntimeException("")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultTransactionAttributeToString() {
|
||||
DefaultTransactionAttribute source = new DefaultTransactionAttribute();
|
||||
source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
source.setTimeout(10);
|
||||
source.setReadOnly(true);
|
||||
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(source.toString());
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertEquals(ta, source);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new RuntimeException()));
|
||||
assertFalse(ta.rollbackOn(new Exception()));
|
||||
|
||||
source.setTimeout(9);
|
||||
assertNotSame(ta, source);
|
||||
source.setTimeout(10);
|
||||
assertEquals(ta, source);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleBasedTransactionAttributeToString() {
|
||||
RuleBasedTransactionAttribute source = new RuleBasedTransactionAttribute();
|
||||
source.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
source.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
source.setTimeout(10);
|
||||
source.setReadOnly(true);
|
||||
source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
|
||||
source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
|
||||
|
||||
TransactionAttributeEditor pe = new TransactionAttributeEditor();
|
||||
pe.setAsText(source.toString());
|
||||
TransactionAttribute ta = (TransactionAttribute) pe.getValue();
|
||||
assertEquals(ta, source);
|
||||
assertEquals(ta.getPropagationBehavior(), TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
assertEquals(ta.getIsolationLevel(), TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
assertEquals(ta.getTimeout(), 10);
|
||||
assertTrue(ta.isReadOnly());
|
||||
assertTrue(ta.rollbackOn(new IllegalArgumentException()));
|
||||
assertFalse(ta.rollbackOn(new IllegalStateException()));
|
||||
|
||||
source.getRollbackRules().clear();
|
||||
assertNotSame(ta, source);
|
||||
source.getRollbackRules().add(new RollbackRuleAttribute("IllegalArgumentException"));
|
||||
source.getRollbackRules().add(new NoRollbackRuleAttribute("IllegalStateException"));
|
||||
assertEquals(ta, source);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class TransactionAttributeSourceAdvisorTests extends TestCase {
|
||||
|
||||
public TransactionAttributeSourceAdvisorTests(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public void testSerializability() throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionAttributes(new Properties());
|
||||
TransactionAttributeSourceAdvisor tas = new TransactionAttributeSourceAdvisor(ti);
|
||||
SerializationTestUtils.serializeAndDeserialize(tas);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Format is
|
||||
* <code>FQN.Method=tx attribute representation</code>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 26.04.2003
|
||||
*/
|
||||
public class TransactionAttributeSourceEditorTests extends TestCase {
|
||||
|
||||
public void testNull() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
pe.setAsText(null);
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
Method m = Object.class.getMethod("hashCode", (Class[]) null);
|
||||
assertTrue(tas.getTransactionAttribute(m, null) == null);
|
||||
}
|
||||
|
||||
public void testInvalid() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
try {
|
||||
pe.setAsText("foo=bar");
|
||||
fail();
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testMatchesSpecific() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
// TODO need FQN?
|
||||
pe.setAsText(
|
||||
"java.lang.Object.hashCode=PROPAGATION_REQUIRED\n" +
|
||||
"java.lang.Object.equals=PROPAGATION_MANDATORY\n" +
|
||||
"java.lang.Object.*it=PROPAGATION_SUPPORTS\n" +
|
||||
"java.lang.Object.notify=PROPAGATION_SUPPORTS\n" +
|
||||
"java.lang.Object.not*=PROPAGATION_REQUIRED");
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
|
||||
TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null), -1);
|
||||
}
|
||||
|
||||
public void testMatchesAll() throws Exception {
|
||||
TransactionAttributeSourceEditor pe = new TransactionAttributeSourceEditor();
|
||||
pe.setAsText("java.lang.Object.*=PROPAGATION_REQUIRED");
|
||||
TransactionAttributeSource tas = (TransactionAttributeSource) pe.getValue();
|
||||
|
||||
checkTransactionProperties(tas, Object.class.getMethod("hashCode", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("equals", new Class[] { Object.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("wait", new Class[] { long.class, int.class }),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notify", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("notifyAll", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
checkTransactionProperties(tas, Object.class.getMethod("toString", (Class[]) null),
|
||||
TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
}
|
||||
|
||||
private void checkTransactionProperties(TransactionAttributeSource tas, Method method, int propagationBehavior) {
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(method, null);
|
||||
if (propagationBehavior >= 0) {
|
||||
assertTrue(ta != null);
|
||||
assertTrue(ta.getIsolationLevel() == TransactionDefinition.ISOLATION_DEFAULT);
|
||||
assertTrue(ta.getPropagationBehavior() == propagationBehavior);
|
||||
}
|
||||
else {
|
||||
assertTrue(ta == null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.transaction.interceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
|
||||
/**
|
||||
* Unit tests for the various {@link TransactionAttributeSource} implementations.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
* @since 15.10.2003
|
||||
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
|
||||
*/
|
||||
public final class TransactionAttributeSourceTests {
|
||||
|
||||
@Test
|
||||
public void testMatchAlwaysTransactionAttributeSource() throws Exception {
|
||||
MatchAlwaysTransactionAttributeSource tas = new MatchAlwaysTransactionAttributeSource();
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertTrue(TransactionDefinition.PROPAGATION_REQUIRED == ta.getPropagationBehavior());
|
||||
|
||||
tas.setTransactionAttribute(new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
ta = tas.getTransactionAttribute(
|
||||
IOException.class.getMethod("getMessage", (Class[]) null), IOException.class);
|
||||
assertNotNull(ta);
|
||||
assertTrue(TransactionDefinition.PROPAGATION_SUPPORTS == ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testMethodMapTransactionAttributeSource() throws NoSuchMethodException {
|
||||
MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put(Object.class.getName() + ".hashCode", TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
methodMap.put(Object.class.getName() + ".toString",
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setMethodMap(methodMap);
|
||||
tas.afterPropertiesSet();
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testMethodMapTransactionAttributeSourceWithLazyInit() throws NoSuchMethodException {
|
||||
MethodMapTransactionAttributeSource tas = new MethodMapTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put(Object.class.getName() + ".hashCode", "PROPAGATION_REQUIRED");
|
||||
methodMap.put(Object.class.getName() + ".toString",
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setMethodMap(methodMap);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Ignore // no longer works now that setMethodMap has been parameterized
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSource() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Map methodMap = new HashMap();
|
||||
methodMap.put("hashCode", "PROPAGATION_REQUIRED");
|
||||
methodMap.put("toString", new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS));
|
||||
tas.setNameMap(methodMap);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
ta = tas.getTransactionAttribute(Object.class.getMethod("toString", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_SUPPORTS, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithStarAtStartOfMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("*ashCode", "PROPAGATION_REQUIRED");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithStarAtEndOfMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("hashCod*", "PROPAGATION_REQUIRED");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceMostSpecificMethodNameIsDefinitelyMatched() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("*", "PROPAGATION_REQUIRED");
|
||||
attributes.put("hashCode", "PROPAGATION_MANDATORY");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNotNull(ta);
|
||||
assertEquals(TransactionDefinition.PROPAGATION_MANDATORY, ta.getPropagationBehavior());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameMatchTransactionAttributeSourceWithEmptyMethodName() throws NoSuchMethodException {
|
||||
NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
|
||||
Properties attributes = new Properties();
|
||||
attributes.put("", "PROPAGATION_MANDATORY");
|
||||
tas.setProperties(attributes);
|
||||
TransactionAttribute ta = tas.getTransactionAttribute(
|
||||
Object.class.getMethod("hashCode", (Class[]) null), null);
|
||||
assertNull(ta);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.interceptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* Mock object based tests for TransactionInterceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @since 16.03.2003
|
||||
*/
|
||||
public class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||
|
||||
protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource[] tas) throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti.setTransactionAttributeSources(tas);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvice(0, ti);
|
||||
return pf.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to create an advised object given the
|
||||
* target object and transaction setup.
|
||||
* Creates a TransactionInterceptor and applies it.
|
||||
*/
|
||||
protected Object advised(Object target, PlatformTransactionManager ptm, TransactionAttributeSource tas) {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionManager(ptm);
|
||||
assertEquals(ptm, ti.getTransactionManager());
|
||||
ti.setTransactionAttributeSource(tas);
|
||||
assertEquals(tas, ti.getTransactionAttributeSource());
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(target);
|
||||
pf.addAdvice(0, ti);
|
||||
return pf.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* A TransactionInterceptor should be serializable if its
|
||||
* PlatformTransactionManager is.
|
||||
*/
|
||||
public void testSerializableWithAttributeProperties() throws Exception {
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("methodName", "PROPAGATION_REQUIRED");
|
||||
ti.setTransactionAttributes(props);
|
||||
PlatformTransactionManager ptm = new SerializableTransactionManager();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
|
||||
|
||||
// Check that logger survived deserialization
|
||||
assertNotNull(ti.logger);
|
||||
assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
|
||||
assertNotNull(ti.getTransactionAttributeSource());
|
||||
}
|
||||
|
||||
public void testSerializableWithCompositeSource() throws Exception {
|
||||
NameMatchTransactionAttributeSource tas1 = new NameMatchTransactionAttributeSource();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("methodName", "PROPAGATION_REQUIRED");
|
||||
tas1.setProperties(props);
|
||||
|
||||
NameMatchTransactionAttributeSource tas2 = new NameMatchTransactionAttributeSource();
|
||||
props = new Properties();
|
||||
props.setProperty("otherMethodName", "PROPAGATION_REQUIRES_NEW");
|
||||
tas2.setProperties(props);
|
||||
|
||||
TransactionInterceptor ti = new TransactionInterceptor();
|
||||
ti.setTransactionAttributeSources(new TransactionAttributeSource[] {tas1, tas2});
|
||||
PlatformTransactionManager ptm = new SerializableTransactionManager();
|
||||
ti.setTransactionManager(ptm);
|
||||
ti = (TransactionInterceptor) SerializationTestUtils.serializeAndDeserialize(ti);
|
||||
|
||||
assertTrue(ti.getTransactionManager() instanceof SerializableTransactionManager);
|
||||
assertTrue(ti.getTransactionAttributeSource() instanceof CompositeTransactionAttributeSource);
|
||||
CompositeTransactionAttributeSource ctas = (CompositeTransactionAttributeSource) ti.getTransactionAttributeSource();
|
||||
assertTrue(ctas.getTransactionAttributeSources()[0] instanceof NameMatchTransactionAttributeSource);
|
||||
assertTrue(ctas.getTransactionAttributeSources()[1] instanceof NameMatchTransactionAttributeSource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We won't use this: we just want to know it's serializable.
|
||||
*/
|
||||
public static class SerializableTransactionManager implements PlatformTransactionManager, Serializable {
|
||||
|
||||
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void commit(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rollback(TransactionStatus status) throws TransactionException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="target" class="org.springframework.beans.DerivedTestBean">
|
||||
<property name="name"><value>custom</value></property>
|
||||
<property name="age"><value>666</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="mockMan" class="org.springframework.transaction.interceptor.PlatformTransactionManagerFacade"/>
|
||||
|
||||
<!--
|
||||
Invalid: we need a transaction attribute source
|
||||
-->
|
||||
<bean id="noTransactionAttributeSource" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="targetDependency" class="org.springframework.beans.TestBean">
|
||||
<property name="name"><value>dependency</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Simple target -->
|
||||
<bean id="target" class="org.springframework.beans.DerivedTestBean" lazy-init="true">
|
||||
<property name="name"><value>custom</value></property>
|
||||
<property name="age"><value>666</value></property>
|
||||
<property name="spouse"><ref local="targetDependency"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
|
||||
|
||||
<bean id="mockMan" class="org.springframework.transaction.interceptor.PlatformTransactionManagerFacade"/>
|
||||
|
||||
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="transactionAttributeSource">
|
||||
<value>
|
||||
org.springframework.beans.ITestBean.s*=PROPAGATION_MANDATORY
|
||||
org.springframework.beans.ITestBean.setAg*=PROPAGATION_REQUIRED
|
||||
org.springframework.beans.ITestBean.set*= PROPAGATION_SUPPORTS , readOnly
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory1" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.springframework.beans.ITestBean</value>
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>txInterceptor</value>
|
||||
<value>target</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="baseProxyFactory" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
|
||||
abstract="true">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="s*">PROPAGATION_MANDATORY</prop>
|
||||
<prop key="setAg*"> PROPAGATION_REQUIRED , readOnly </prop>
|
||||
<prop key="set*">PROPAGATION_SUPPORTS</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory2DynamicProxy" parent="baseProxyFactory">
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
Same as proxyFactory2DynamicProxy but forces the use of CGLIB.
|
||||
-->
|
||||
<bean id="proxyFactory2Cglib" parent="baseProxyFactory">
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="target"><ref local="target"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory2Lazy" parent="baseProxyFactory">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.aop.target.LazyInitTargetSource">
|
||||
<property name="targetBeanName"><idref local="target"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="proxyFactory3" parent="baseProxyFactory">
|
||||
<property name="target"><ref local="target"/></property>
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="pointcut">
|
||||
<ref local="txnInvocationCounterPointcut"/>
|
||||
</property>
|
||||
<property name="preInterceptors">
|
||||
<list>
|
||||
<ref local="preInvocationCounterInterceptor"/>
|
||||
</list>
|
||||
</property>
|
||||
<property name="postInterceptors">
|
||||
<list>
|
||||
<ref local="postInvocationCounterInterceptor"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean name="cglibNoInterfaces" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<property name="target">
|
||||
<bean class="org.springframework.transaction.interceptor.ImplementsNoInterfaces">
|
||||
<property name="dependency"><ref local="targetDependency"/></property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">PROPAGATION_REQUIRED</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
The HotSwappableTargetSource is a Type 3 component.
|
||||
-->
|
||||
<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
|
||||
<constructor-arg><ref local="target"/></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="hotSwapped" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|
||||
<property name="transactionManager"><ref local="mockMan"/></property>
|
||||
<!-- Should automatically pick up the target source, rather than simple target -->
|
||||
<property name="target"><ref local="swapper"/></property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="s*">PROPAGATION_MANDATORY</prop>
|
||||
<prop key="setAg*">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="set*">PROPAGATION_SUPPORTS</prop>
|
||||
</props>
|
||||
</property>
|
||||
<property name="proxyTargetClass"><value>true</value></property>
|
||||
<property name="optimize"><value>false</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="txnInvocationCounterPointcut"
|
||||
class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterPointcut"/>
|
||||
|
||||
<bean id="preInvocationCounterInterceptor" class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterInterceptor"/>
|
||||
|
||||
<bean id="postInvocationCounterInterceptor" class="org.springframework.transaction.interceptor.BeanFactoryTransactionTests$InvocationCounterInterceptor"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.transaction.jta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.transaction.Synchronization;
|
||||
|
||||
import com.ibm.wsspi.uow.UOWAction;
|
||||
import com.ibm.wsspi.uow.UOWActionException;
|
||||
import com.ibm.wsspi.uow.UOWException;
|
||||
import com.ibm.wsspi.uow.UOWManager;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MockUOWManager implements UOWManager {
|
||||
|
||||
private int type = UOW_TYPE_GLOBAL_TRANSACTION;
|
||||
|
||||
private boolean joined;
|
||||
|
||||
private int timeout;
|
||||
|
||||
private boolean rollbackOnly;
|
||||
|
||||
private int status = UOW_STATUS_NONE;
|
||||
|
||||
private final Map resources = new HashMap();
|
||||
|
||||
private final List synchronizations = new LinkedList();
|
||||
|
||||
|
||||
public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWActionException, UOWException {
|
||||
this.type = type;
|
||||
this.joined = join;
|
||||
try {
|
||||
this.status = UOW_STATUS_ACTIVE;
|
||||
action.run();
|
||||
this.status = (this.rollbackOnly ? UOW_STATUS_ROLLEDBACK : UOW_STATUS_COMMITTED);
|
||||
}
|
||||
catch (Error err) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw err;
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
this.status = UOW_STATUS_ROLLEDBACK;
|
||||
throw new UOWActionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public int getUOWType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public boolean getJoined() {
|
||||
return this.joined;
|
||||
}
|
||||
|
||||
public long getLocalUOWId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setUOWTimeout(int uowType, int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public int getUOWTimeout() {
|
||||
return this.timeout;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
this.rollbackOnly = true;
|
||||
}
|
||||
|
||||
public boolean getRollbackOnly() {
|
||||
return this.rollbackOnly;
|
||||
}
|
||||
|
||||
public void setUOWStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getUOWStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public void putResource(Object key, Object value) {
|
||||
this.resources.put(key, value);
|
||||
}
|
||||
|
||||
public Object getResource(Object key) throws NullPointerException {
|
||||
return this.resources.get(key);
|
||||
}
|
||||
|
||||
public void registerInterposedSynchronization(Synchronization sync) {
|
||||
this.synchronizations.add(sync);
|
||||
}
|
||||
|
||||
public List getSynchronizations() {
|
||||
return this.synchronizations;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
/*
|
||||
* 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.transaction.jta;
|
||||
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import com.ibm.wsspi.uow.UOWAction;
|
||||
import com.ibm.wsspi.uow.UOWException;
|
||||
import com.ibm.wsspi.uow.UOWManager;
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.NestedTransactionNotSupportedException;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class WebSphereUowTransactionManagerTests extends TestCase {
|
||||
|
||||
public void testUowManagerFoundInJndi() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
ExpectedLookupTemplate jndiTemplate =
|
||||
new ExpectedLookupTemplate(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testUowManagerAndUserTransactionFoundInJndi() 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);
|
||||
utControl.replay();
|
||||
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
|
||||
jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut);
|
||||
jndiTemplate.addObject(WebSphereUowTransactionManager.DEFAULT_UOW_MANAGER_NAME, manager);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager();
|
||||
ptm.setJndiTemplate(jndiTemplate);
|
||||
ptm.afterPropertiesSet();
|
||||
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
TransactionStatus ts = ptm.getTransaction(definition);
|
||||
ptm.commit(ts);
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testPropagationMandatoryFailsInCaseOfNoExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown IllegalTransactionStateException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupports() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupported() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchOnActual() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationSupportsAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_SUPPORTS, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNotSupportedAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NOT_SUPPORTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionSynchronizationUsingPropagationNeverAndSynchNever() {
|
||||
doTestNewTransactionSynchronization(
|
||||
TransactionDefinition.PROPAGATION_NEVER, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
private void doTestNewTransactionSynchronization(int propagationBehavior, final int synchMode) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
ptm.setTransactionSynchronization(synchMode);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(propagationBehavior);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
if (synchMode == WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
else {
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequired() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNew() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNested() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ALWAYS);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNestedAndSynchOnActual() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiredAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationRequiresNewAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_REQUIRES_NEW, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitUsingPropagationNestedAndSynchNever() {
|
||||
doTestNewTransactionWithCommit(
|
||||
TransactionDefinition.PROPAGATION_NESTED, WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER);
|
||||
}
|
||||
|
||||
private void doTestNewTransactionWithCommit(int propagationBehavior, final int synchMode) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
ptm.setTransactionSynchronization(synchMode);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(propagationBehavior);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
if (synchMode != WebSphereUowTransactionManager.SYNCHRONIZATION_NEVER) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
else {
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
}
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitAndTimeout() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setTimeout(10);
|
||||
definition.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(10, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithCommitException() {
|
||||
final RollbackException rex = new RollbackException();
|
||||
MockUOWManager manager = new MockUOWManager() {
|
||||
public void runUnderUOW(int type, boolean join, UOWAction action) throws UOWException {
|
||||
throw new UOWException(rex);
|
||||
}
|
||||
};
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown TransactionSystemException");
|
||||
}
|
||||
catch (TransactionSystemException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getCause() instanceof UOWException);
|
||||
assertSame(rex, ex.getRootCause());
|
||||
assertSame(rex, ex.getMostSpecificCause());
|
||||
}
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithRollback() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
throw new OptimisticLockingFailureException("");
|
||||
}
|
||||
});
|
||||
fail("Should have thrown OptimisticLockingFailureException");
|
||||
}
|
||||
catch (OptimisticLockingFailureException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testNewTransactionWithRollbackOnly() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
status.setRollbackOnly();
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertTrue(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingNonSpringTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertTrue(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testPropagationNeverFailsInCaseOfExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown IllegalTransactionStateException");
|
||||
}
|
||||
catch (IllegalTransactionStateException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testPropagationNestedFailsInCaseOfExistingTransaction() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
manager.setUOWStatus(UOWManager.UOW_STATUS_ACTIVE);
|
||||
WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
|
||||
|
||||
try {
|
||||
ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
return "result";
|
||||
}
|
||||
});
|
||||
fail("Should have thrown NestedTransactionNotSupportedException");
|
||||
}
|
||||
catch (NestedTransactionNotSupportedException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationRequired() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationSupports() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithParticipationUsingPropagationMandatory() {
|
||||
doTestExistingTransactionWithParticipation(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
}
|
||||
|
||||
private void doTestExistingTransactionWithParticipation(int propagationBehavior) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(propagationBehavior);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
assertTrue(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithSuspensionUsingPropagationRequiresNew() {
|
||||
doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
}
|
||||
|
||||
public void testExistingTransactionWithSuspensionUsingPropagationNotSupported() {
|
||||
doTestExistingTransactionWithSuspension(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
private void doTestExistingTransactionWithSuspension(final int propagationBehavior) {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(propagationBehavior);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertEquals(propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW,
|
||||
TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
if (propagationBehavior == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
|
||||
assertEquals(UOWManager.UOW_TYPE_GLOBAL_TRANSACTION, manager.getUOWType());
|
||||
}
|
||||
else {
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
}
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
public void testExistingTransactionUsingPropagationNotSupported() {
|
||||
MockUOWManager manager = new MockUOWManager();
|
||||
final WebSphereUowTransactionManager ptm = new WebSphereUowTransactionManager(manager);
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
final DefaultTransactionDefinition definition2 = new DefaultTransactionDefinition();
|
||||
definition2.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
|
||||
definition2.setReadOnly(true);
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals("result", ptm.execute(definition, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertEquals("result2", ptm.execute(definition2, new TransactionCallback() {
|
||||
public Object doInTransaction(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertTrue(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
return "result2";
|
||||
}
|
||||
}));
|
||||
return "result";
|
||||
}
|
||||
}));
|
||||
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
|
||||
assertEquals(0, manager.getUOWTimeout());
|
||||
assertEquals(UOWManager.UOW_TYPE_LOCAL_TRANSACTION, manager.getUOWType());
|
||||
assertFalse(manager.getJoined());
|
||||
assertFalse(manager.getRollbackOnly());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.transaction.support;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class JtaTransactionManagerSerializationTests extends TestCase {
|
||||
|
||||
public void testSerializable() throws Exception {
|
||||
MockControl utMock = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utMock.getMock();
|
||||
MockControl ut2Mock = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut2 = (UserTransaction) ut2Mock.getMock();
|
||||
MockControl tmMock = MockControl.createControl(TransactionManager.class);
|
||||
TransactionManager tm = (TransactionManager) tmMock.getMock();
|
||||
|
||||
JtaTransactionManager jtam = new JtaTransactionManager();
|
||||
jtam.setUserTransaction(ut);
|
||||
jtam.setTransactionManager(tm);
|
||||
jtam.setRollbackOnCommitFailure(true);
|
||||
jtam.afterPropertiesSet();
|
||||
|
||||
SimpleNamingContextBuilder jndiEnv = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
|
||||
jndiEnv.bind(JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME, ut2);
|
||||
JtaTransactionManager serializedJtatm =
|
||||
(JtaTransactionManager) SerializationTestUtils.serializeAndDeserialize(jtam);
|
||||
|
||||
// should do client-side lookup
|
||||
assertNotNull("Logger must survive serialization", serializedJtatm.logger);
|
||||
assertTrue("UserTransaction looked up on client", serializedJtatm.getUserTransaction() == ut2);
|
||||
assertNull("TransactionManager didn't survive", serializedJtatm.getTransactionManager());
|
||||
assertEquals(true, serializedJtatm.isRollbackOnCommitFailure());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor pointcut="execution(* *..ITestBean.*(..))" advice-ref="txAdvice"/>
|
||||
</aop:config>
|
||||
|
||||
<tx:advice id="txAdvice">
|
||||
<tx:attributes>
|
||||
<tx:method name="get*" read-only="true"/>
|
||||
<tx:method name="set*"/>
|
||||
<tx:method name="exceptional"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<tx:advice id="txRollbackAdvice">
|
||||
<tx:attributes>
|
||||
<tx:method name="get*" rollback-for="java.lang.Exception"/>
|
||||
<tx:method name="set*" no-rollback-for="java.lang.RuntimeException"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.transaction.CallCountingTransactionManager"/>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user