/**
* Created on Mar 14, 2006
*
* $Id$
* $Revision$
*/
package org.springmodules.javaspaces.tx;
import java.rmi.RemoteException;
import net.jini.core.entry.Entry;
import net.jini.core.entry.UnusableEntryException;
import net.jini.core.lease.Lease;
import net.jini.core.transaction.Transaction;
import net.jini.core.transaction.TransactionException;
import net.jini.core.transaction.server.TransactionManager;
import net.jini.space.JavaSpace;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springmodules.javaspaces.JavaSpaceCallback;
import org.springmodules.javaspaces.JavaSpaceTemplate;
import org.springmodules.jini.JiniUtils;
/**
* Functional tx tests - require the transaction service to be started.
*
* @author Costin Leau
*
*/
public class TxTests extends AbstractDependencyInjectionSpringContextTests {
/**
* @see org.springmodules.test.AbstractDependencyInjectionSpringContextTests#getConfigLocations()
*/
protected String[] getConfigLocations() {
return new String[] { "/org/springmodules/javaspaces/tx/tx-context.xml" };
}
private TransactionManager tm;
private TransactionTemplate txTemplate;
private JavaSpace space;
private JavaSpaceTemplate spaceTemplate;
public void testTM() {
assertNotNull(tm);
}
public void testSimpleTransaction() throws Exception {
assertNotNull(txTemplate);
final Entry myEntry = new Entry() {
};
txTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// we need to pass in a tx
assertNotNull("no tx started", JiniUtils.getTransaction(space));
}
});
}
public void testRollbackScenario() throws Exception {
final SomeBean template = new SomeBean();
final long timeout = 1000 * 2;
assertNull(spaceTemplate.read(template, timeout));
final RuntimeException EXCEPTION = new RuntimeException("intentional exception");
try {
txTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
spaceTemplate.execute(new JavaSpaceCallback() {
public Object doInSpace(JavaSpace js, Transaction transaction)
throws RemoteException, TransactionException, UnusableEntryException,
InterruptedException {
// check that we have a tx
assertNotNull("no tx started", transaction);
Object result = js.read(template, transaction, timeout);
assertNull(result);
js.write(template, transaction, Lease.FOREVER);
result = js.read(template, transaction, timeout);
assertNotNull(result);
throw EXCEPTION;
}
});
}
});
}
catch (RuntimeException re) {
// it's okay (if it's our exception)
assertSame(EXCEPTION, re);
}
assertNull(spaceTemplate.read(template, timeout));
}
public void testPropagationNotSupported() throws Exception {
final SomeBean template = new SomeBean();
final SomeBean anotherTemplate = new SomeBean();
anotherTemplate.name = "another bean";
final long timeout = 1000 * 2;
final TransactionTemplate notSupportedTransaction = new TransactionTemplate(
txTemplate.getTransactionManager());
notSupportedTransaction.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
notSupportedTransaction.afterPropertiesSet();
final TransactionTemplate mandatoryTransaction = new TransactionTemplate(txTemplate.getTransactionManager());
mandatoryTransaction.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
mandatoryTransaction.afterPropertiesSet();
final RuntimeException EXCEPTION = new RuntimeException("intentional exception");
try {
// start tx (REQUIRED)
txTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(final TransactionStatus status) {
spaceTemplate.execute(new JavaSpaceCallback() {
public Object doInSpace(JavaSpace js, final Transaction transaction)
throws RemoteException, TransactionException, UnusableEntryException,
InterruptedException {
// check that we have a tx
assertNotNull("no tx started", transaction);
Object result = js.read(template, transaction, timeout);
assertNull(result);
// write
js.write(template, transaction, Lease.ANY);
notSupportedTransaction.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(final TransactionStatus status2) {
spaceTemplate.execute(new JavaSpaceCallback() {
public Object doInSpace(JavaSpace js2, Transaction transaction2)
throws RemoteException, TransactionException,
UnusableEntryException, InterruptedException {
// NOT_SUPPORTED means tx was suspended
assertNull(transaction2);
assertSame(transaction2, JiniUtils.getTransaction(space));
js2.write(anotherTemplate, transaction2, Lease.ANY);
// check object from
// find the object in the parent transaction
Object rez = js2.read(template, transaction, timeout);
assertNotNull(rez);
// but not in child transaction (NOT_SUPPORTED)
rez = js2.read(template, transaction2, timeout);
assertNull(rez);
rez = js2.read(anotherTemplate, transaction2, timeout);
assertNotNull(rez);
return null;
}
});
}
});
// find the template
result = js.read(template, transaction, timeout);
assertNotNull(result);
result = js.read(anotherTemplate, transaction, timeout);
assertNotNull(result);
return mandatoryTransaction.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
Transaction tx = JiniUtils.getTransaction(space);
assertSame(transaction ,tx);
assertNotNull(spaceTemplate.readIfExists(template,timeout));
throw EXCEPTION;
}
});
}
});
}
});
}
catch (RuntimeException e) {
// it's okay (if it's ours)
assertSame(EXCEPTION, e);
assertNull(spaceTemplate.readIfExists(template, timeout));
assertNotNull(spaceTemplate.readIfExists(anotherTemplate, timeout));
}
}
/**
* @return Returns the tm.
*/
public TransactionManager getTm() {
return tm;
}
/**
* @param tm
* The tm to set.
*/
public void setTm(TransactionManager tm) {
this.tm = tm;
}
public TransactionTemplate getTxTemplate() {
return txTemplate;
}
public void setTxTemplate(TransactionTemplate txTemplate) {
this.txTemplate = txTemplate;
}
public JavaSpace getSpace() {
return space;
}
public void setSpace(JavaSpace space) {
this.space = space;
}
public JavaSpaceTemplate getSpaceTemplate() {
return spaceTemplate;
}
public void setSpaceTemplate(JavaSpaceTemplate spaceTemplate) {
this.spaceTemplate = spaceTemplate;
}
}