package org.springmodules.jcr.jackrabbit;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import junit.framework.TestCase;
import org.apache.jackrabbit.api.XASession;
import org.easymock.MockControl;
import org.springframework.transaction.InvalidIsolationLevelException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springmodules.jcr.JcrCallback;
import org.springmodules.jcr.JcrTemplate;
import org.springmodules.jcr.SessionFactory;
import org.springmodules.jcr.SessionHolderProviderManager;
import org.springmodules.jcr.jackrabbit.support.UserTxSessionHolder;
import org.springmodules.jcr.support.ListSessionHolderProviderManager;
public class LocalTransactionManagerTests extends TestCase {
public void testTransactionCommit() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(XASession.class);
final XASession session = (XASession) sessionControl.getMock();
// create nice mock
MockControl xaResControl = MockControl.createControl(XAResource.class);
XAResource xaRes = (XAResource) xaResControl.getMock();
sfControl.expectAndReturn(sf.getSession(), session);
sessionControl.expectAndReturn(session.getXAResource(), xaRes);
session.save();
session.logout();
/*
* MockControl repositoryControl =
* MockControl.createNiceControl(Repository.class); Repository
* repository = (Repository) repositoryControl.getMock();
* repositoryControl.replay();
*
* sessionControl.expectAndReturn(session.getRepository(), repository,
* MockControl.ONE_OR_MORE); final SessionHolderProviderManager
* providerManager = new ListSessionHolderProviderManager();
*
*/
Xid xidMock = new XidMock();
xaRes.start(xidMock, XAResource.TMNOFLAGS);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.prepare(xidMock);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaResControl.setReturnValue(0);
xaRes.commit(xidMock, false);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.end(xidMock, XAResource.TMSUCCESS);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
sfControl.replay();
sessionControl.replay();
xaResControl.replay();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.save();
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
sessionControl.verify();
xaResControl.verify();
}
public void testTransactionRollback() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(XASession.class);
final XASession session = (XASession) sessionControl.getMock();
// create nice mock
MockControl xaResControl = MockControl.createControl(XAResource.class);
XAResource xaRes = (XAResource) xaResControl.getMock();
sfControl.expectAndReturn(sf.getSession(), session);
sessionControl.expectAndReturn(session.getXAResource(), xaRes);
session.save();
session.logout();
/*
* // used for ServiceProvider MockControl repositoryControl =
* MockControl.createNiceControl(Repository.class); Repository
* repository = (Repository) repositoryControl.getMock();
* repositoryControl.replay();
*
* sessionControl.expectAndReturn(session.getRepository(), repository,
* MockControl.ONE_OR_MORE);
*/
Xid xidMock = new XidMock();
xaRes.start(xidMock, XAResource.TMNOFLAGS);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.end(xidMock, XAResource.TMFAIL);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.rollback(xidMock);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
sfControl.replay();
sessionControl.replay();
xaResControl.replay();
final SessionHolderProviderManager providerManager = new ListSessionHolderProviderManager();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
try {
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.execute(new JcrCallback() {
public Object doInJcr(Session se) throws RepositoryException {
se.save();
throw new RuntimeException();
}
});
}
});
}
catch (RuntimeException e) {
// it's okay
}
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
sessionControl.verify();
xaResControl.verify();
}
public void testTransactionRollbackOnly() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(XASession.class);
final XASession session = (XASession) sessionControl.getMock();
// create nice mock
MockControl xaResControl = MockControl.createControl(XAResource.class);
XAResource xaRes = (XAResource) xaResControl.getMock();
sfControl.expectAndReturn(sf.getSession(), session);
sessionControl.expectAndReturn(session.getXAResource(), xaRes);
session.save();
session.logout();
Xid xidMock = new XidMock();
xaRes.start(xidMock, XAResource.TMNOFLAGS);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.end(xidMock, XAResource.TMFAIL);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
xaRes.rollback(xidMock);
xaResControl.setMatcher(MockControl.ALWAYS_MATCHER);
sfControl.replay();
sessionControl.replay();
xaResControl.replay();
final SessionHolderProviderManager providerManager = new ListSessionHolderProviderManager();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
final List l = new ArrayList();
l.add("test");
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.execute(new JcrCallback() {
public Object doInJcr(Session se) throws RepositoryException {
se.save();
return null;
}
});
status.setRollbackOnly();
}
});
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
sessionControl.verify();
xaResControl.verify();
}
public void testInvalidIsolation() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
sfControl.replay();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
tt.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
try {
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.execute(new JcrCallback() {
public Object doInJcr(Session session) throws RepositoryException {
return null;
}
});
}
});
fail("Should have thrown InvalidIsolationLevelException");
}
catch (InvalidIsolationLevelException e) {
// it's okay
}
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
}
public void testTransactionCommitWithPrebound() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(XASession.class);
final XASession session = (XASession) sessionControl.getMock();
MockControl xaResControl = MockControl.createControl(XAResource.class);
XAResource xaRes = (XAResource) xaResControl.getMock();
sessionControl.expectAndReturn(session.getXAResource(), xaRes);
session.save();
sfControl.replay();
sessionControl.replay();
xaResControl.replay();
final SessionHolderProviderManager providerManager = new ListSessionHolderProviderManager();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
UserTxSessionHolder uTx = new UserTxSessionHolder(session);
TransactionSynchronizationManager.bindResource(sf, uTx);
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.save();
}
});
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
TransactionSynchronizationManager.unbindResource(sf);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
sessionControl.verify();
xaResControl.verify();
}
public void testTransactionRollbackOnlyWithPrebound() throws Exception {
MockControl sfControl = MockControl.createControl(SessionFactory.class);
final SessionFactory sf = (SessionFactory) sfControl.getMock();
MockControl sessionControl = MockControl.createControl(XASession.class);
final XASession session = (XASession) sessionControl.getMock();
MockControl xaResControl = MockControl.createControl(XAResource.class);
XAResource xaRes = (XAResource) xaResControl.getMock();
sessionControl.expectAndReturn(session.getXAResource(), xaRes);
session.save();
sfControl.replay();
sessionControl.replay();
xaResControl.replay();
PlatformTransactionManager tm = new LocalTransactionManager(sf);
TransactionTemplate tt = new TransactionTemplate(tm);
UserTxSessionHolder uTx = new UserTxSessionHolder(session);
TransactionSynchronizationManager.bindResource(sf, uTx);
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
uTx.setRollbackOnly();
try {
tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
JcrTemplate template = new JcrTemplate(sf);
template.save();
}
});
}
catch (UnexpectedRollbackException e) {
System.out.println(e);
}
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
TransactionSynchronizationManager.unbindResource(sf);
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
sfControl.verify();
sessionControl.verify();
xaResControl.verify();
}
/**
* Simple mock which overrides equals.
*
* @author Costin Leau
*
*/
protected class XidMock implements Xid {
/**
* @see javax.transaction.xa.Xid#getBranchQualifier()
*/
public byte[] getBranchQualifier() {
return null;
}
/**
* @see javax.transaction.xa.Xid#getFormatId()
*/
public int getFormatId() {
return 0;
}
/**
* @see javax.transaction.xa.Xid#getGlobalTransactionId()
*/
public byte[] getGlobalTransactionId() {
return null;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return true;
}
}
}