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);
        }
    }

}

Reply via email to