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.