You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by "Cele Liu (JIRA)" <ji...@apache.org> on 2009/11/04 04:51:34 UTC

[jira] Created: (JCR-2382) NPE when calling node.getBaseVersion() within the transaction.

NPE when calling node.getBaseVersion() within the transaction.
--------------------------------------------------------------

                 Key: JCR-2382
                 URL: https://issues.apache.org/jira/browse/JCR-2382
             Project: Jackrabbit Content Repository
          Issue Type: Bug
          Components: jackrabbit-core
    Affects Versions: 1.6.0
         Environment: winxp
            Reporter: Cele Liu


We try to get the base version from a versionable node in the transaction, but if we didn't check in the node, the NPE will throw out. We used the jr-jcr to support XA transaction.
the code likes:
        UserTransaction ut = null;
        InitialContext tx = new InitialContext();
        ut = (UserTransaction) tx.lookup("UserTransaction");
        ut.begin();
        try {
            Session session = getJcrSession();
            Node root = session.getRootNode();
            Node child = root.addNode("testchild");
            root.save();
            child.addMixin(JcrConstants.MIX_VERSIONABLE);
            child.save();
            session.save();
            //child.checkin();
            javax.jcr.version.Version v = child.getBaseVersion();
            session.logout();
            ut.commit();
        }catch(Exception e){
            ut.rollback();
            e.printStackTrace(System.err);
            fail("failed with " + e.getMessage());
        }
The exception stack:
java.lang.NullPointerException
      at org.apache.jackrabbit.core.NodeImpl.getBaseVersion(NodeImpl.java:3659)
      at com.vitria.modeling.repository.sapi.JcrTransactionTest.testBaseVersionableSample(JcrTransac
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

If we did not run the code in XA transaction or check-in the code before calling the child.getBaseVersion(), the NPE will be gone.
JR1.5.0 doesn't have this issue.

I compare the code between JR1.5.0 and JR 1.6.0. and get some clue.

Please check the code snippet for JR 1.6.0. Looks like in JR 1.6.0, it always look up the node from the version manager.
The NPE happens if the versioned node doesn't exist, v is null and then JR try to get node by the v.getId().

public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
        // check state of this instance
        sanityCheck();
        boolean isFull = checkVersionable();
        InternalVersion v;
        if (isFull) {
            NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
            v = session.getVersionManager().getVersion(id);
        } else {
            // note, that the method currently only works for linear version
            // graphs (i.e. simple versioning)
            v = session.getVersionManager().getHeadVersionOfNode(((NodeId) id));
        }
        return (Version) session.getNodeById(v.getId());
}

And there is the code snippet for JR 1.5.0, JR doesn't depends on the version manager, it always get the version from the property.

public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
        // check state of this instance
        sanityCheck();
        checkVersionable();
       // transactions workaround.
        NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
        session.getVersionManager().getVersion(id);
        return (Version) getProperty(NameConstants.JCR_BASEVERSION).getNode();
}

Notice: For JR 1.5.0 and JR 1.6.0, if you didn't check in the node in XA transaction, the API session.getVersionManager().getVersion(id); both will return null.
The difference is 1.6.0 will use the return to perform the look-up, and 1.5.0 doesn't. 

After I patch the code to below, the getBaseVersion() cases got passed:
public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
        // check state of this instance
        sanityCheck();
        boolean isFull = checkVersionable();
        InternalVersion v;
        if (isFull) {
            NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
            v = session.getVersionManager().getVersion(id);
        } else {
            // note, that the method currently only works for linear version
            // graphs (i.e. simple versioning)
            v = session.getVersionManager().getHeadVersionOfNode(((NodeId) id));
        }
        if (v == null){
            return (Version) getProperty(NameConstants.JCR_BASEVERSION).getNode();
        }else{
            return (Version) session.getNodeById(v.getId());    
        }
}




-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (JCR-2382) NPE when calling node.getBaseVersion() within the transaction.

Posted by "Benjamin Brown (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/JCR-2382?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12891554#action_12891554 ] 

Benjamin Brown commented on JCR-2382:
-------------------------------------

The same fault has been noticed when operating Jackrabbit 1.6.2 in a cluster (not sure if the cluster has any bearing on the issue) and an update to existing content is being performed. About 70% of the time it is successful otherwise it throws an NPE. The patch provided by the OP does fix the issue.

> NPE when calling node.getBaseVersion() within the transaction.
> --------------------------------------------------------------
>
>                 Key: JCR-2382
>                 URL: https://issues.apache.org/jira/browse/JCR-2382
>             Project: Jackrabbit Content Repository
>          Issue Type: Bug
>          Components: jackrabbit-core
>    Affects Versions: 1.6.0
>         Environment: winxp
>            Reporter: Cele Liu
>
> We try to get the base version from a versionable node in the transaction, but if we didn't check in the node, the NPE will throw out. We used the jr-jcr to support XA transaction.
> the code likes:
>         UserTransaction ut = null;
>         InitialContext tx = new InitialContext();
>         ut = (UserTransaction) tx.lookup("UserTransaction");
>         ut.begin();
>         try {
>             Session session = getJcrSession();
>             Node root = session.getRootNode();
>             Node child = root.addNode("testchild");
>             root.save();
>             child.addMixin(JcrConstants.MIX_VERSIONABLE);
>             child.save();
>             session.save();
>             //child.checkin();
>             javax.jcr.version.Version v = child.getBaseVersion();
>             session.logout();
>             ut.commit();
>         }catch(Exception e){
>             ut.rollback();
>             e.printStackTrace(System.err);
>             fail("failed with " + e.getMessage());
>         }
> The exception stack:
> java.lang.NullPointerException
>       at org.apache.jackrabbit.core.NodeImpl.getBaseVersion(NodeImpl.java:3659)
>       at com.vitria.modeling.repository.sapi.JcrTransactionTest.testBaseVersionableSample(JcrTransac
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> If we did not run the code in XA transaction or check-in the code before calling the child.getBaseVersion(), the NPE will be gone.
> JR1.5.0 doesn't have this issue.
> I compare the code between JR1.5.0 and JR 1.6.0. and get some clue.
> Please check the code snippet for JR 1.6.0. Looks like in JR 1.6.0, it always look up the node from the version manager.
> The NPE happens if the versioned node doesn't exist, v is null and then JR try to get node by the v.getId().
> public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
>         // check state of this instance
>         sanityCheck();
>         boolean isFull = checkVersionable();
>         InternalVersion v;
>         if (isFull) {
>             NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
>             v = session.getVersionManager().getVersion(id);
>         } else {
>             // note, that the method currently only works for linear version
>             // graphs (i.e. simple versioning)
>             v = session.getVersionManager().getHeadVersionOfNode(((NodeId) id));
>         }
>         return (Version) session.getNodeById(v.getId());
> }
> And there is the code snippet for JR 1.5.0, JR doesn't depends on the version manager, it always get the version from the property.
> public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
>         // check state of this instance
>         sanityCheck();
>         checkVersionable();
>        // transactions workaround.
>         NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
>         session.getVersionManager().getVersion(id);
>         return (Version) getProperty(NameConstants.JCR_BASEVERSION).getNode();
> }
> Notice: For JR 1.5.0 and JR 1.6.0, if you didn't check in the node in XA transaction, the API session.getVersionManager().getVersion(id); both will return null.
> The difference is 1.6.0 will use the return to perform the look-up, and 1.5.0 doesn't. 
> After I patch the code to below, the getBaseVersion() cases got passed:
> public Version getBaseVersion() throws UnsupportedRepositoryOperationException, RepositoryException {
>         // check state of this instance
>         sanityCheck();
>         boolean isFull = checkVersionable();
>         InternalVersion v;
>         if (isFull) {
>             NodeId id = NodeId.valueOf(getProperty(NameConstants.JCR_BASEVERSION).getString());
>             v = session.getVersionManager().getVersion(id);
>         } else {
>             // note, that the method currently only works for linear version
>             // graphs (i.e. simple versioning)
>             v = session.getVersionManager().getHeadVersionOfNode(((NodeId) id));
>         }
>         if (v == null){
>             return (Version) getProperty(NameConstants.JCR_BASEVERSION).getNode();
>         }else{
>             return (Version) session.getNodeById(v.getId());    
>         }
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.