Hi,
I have big problems with transactions using XASession. The following
code runs ok without transactions, but when transactions are used, it fails:
Node versionableParent =
session.getRootNode().getNode(PARENT_NODE_NAME); //mix:versionable
versionableParent.checkout();
Node node = versionableParent.addNode("NODE");
node.addMixin("mix:versionable");
versionableParent.save();
node.checkin(); <=========(*)
versionableParent.checkin();
log.info("node.isCheckedOut()" + node.isCheckedOut());
In transaction, (*) line doesn't make the node check in (it stays
checked out) and trying to commit the transaction causes:
15:41:14,434 ERROR (TransactionalItemStateManager.java:114) -
org.apache.jackrabbit.core.state.NoSuchItemStateException:
31f78b39-6422-4ec8-b41e-2571b6807b05/{http://www.jcp.org/jcr/1.0}isCheckedOut
java.lang.Exception: Cannot commit transaction.
[...]
Caused by: org.apache.jackrabbit.core.state.TransactionException: Unable
to commit transaction.:
31f78b39-6422-4ec8-b41e-2571b6807b05/{http://www.jcp.org/jcr/1.0}isCheckedOut
[...]
Caused by: org.apache.jackrabbit.core.state.NoSuchItemStateException:
31f78b39-6422-4ec8-b41e-2571b6807b05/{http://www.jcp.org/jcr/1.0}isCheckedOut
When I removed (*) line, transaction commits well, but the node stays
checked out...
Any ideas?
PS.
I can send you a simple code that shows the problem if you want.
--
Best Regards, Senior developer at Cognifide
Marcin Cenkier www.cognifide.com
package org.alsoft.jcr.spring;
import javax.jcr.Node;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.jackrabbit.core.XASession;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springmodules.jcr.JcrSessionFactory;
/**
* Tests transactions in Jackrabbit.
*
* @author marcin_cenkier
*/
public class JRTest {
private static final org.apache.commons.logging.Log log =
org.apache.commons.logging.LogFactory.getLog(JRTest.class);
private static class MyXid implements Xid {
byte b;
public MyXid(int b) {
this.b = (byte) (b & 0xff);
}
public byte[] getBranchQualifier() {
return new byte[0];
}
public int getFormatId() {
return 0;
}
public byte[] getGlobalTransactionId() {
return new byte[b];
}
}
private static interface Callback {
public Object run() throws Exception;
}
public static Object runInTransaction(Callback c, XAResource xaResource,
int transactionId) throws Throwable {
// create dummy Xid
Xid xid;
xid = new MyXid(transactionId);
try {
xaResource.start(xid, XAResource.TMNOFLAGS);
Object retValue = c.run();
xaResource.end(xid, XAResource.TMSUCCESS);
xaResource.prepare(xid);
xaResource.commit(xid, false);
return retValue;
}
catch (XAException e) {
throw new Exception("Cannot commit transaction.", e);
}
catch (Throwable e) {
xaResource.end(xid, XAResource.TMFAIL);
xaResource.prepare(xid);
xaResource.rollback(xid);
throw e;
}
}
public static void jackrabbitTransactionTest() throws Throwable {
final String PARENT_NODE_NAME = "PARENT_NODE_NAME";
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
JcrSessionFactory jcrSessionFactory = (JcrSessionFactory)
ctx.getBean("jcrSessionFactory");
final XASession session = (XASession) jcrSessionFactory.getSession();
XAResource xaResource = session.getXAResource();
Callback callback = new Callback() {
public Object run() throws Exception {
Node parentNode = session.getRootNode();
try {
parentNode.getNode(PARENT_NODE_NAME);
}
catch (Exception e) {
Node node = parentNode.addNode(PARENT_NODE_NAME);
node.addMixin("mix:versionable");
parentNode.save();
}
Node versionableParent =
session.getRootNode().getNode(PARENT_NODE_NAME);
log.info("versionableParent.isCheckedOut()" +
versionableParent.isCheckedOut());
versionableParent.checkout();
Node node = versionableParent.addNode("NODE");
node.addMixin("mix:versionable");
log.info("created node [" + node.getName() + "]");
versionableParent.save();
node.checkin();
versionableParent.checkin();
log.info("node.isCheckedOut()" + node.isCheckedOut());
return null;
}
};
log.info("=== Outside transaction");
callback.run();
log.info("=== Inside transaction");
runInTransaction(callback, xaResource, 1);
}
public static void main(String[] args) {
try {
jackrabbitTransactionTest();
}
catch (Throwable e) {
log.error("", e);
}
}
}