nt:versionedChild problem
-------------------------
Key: JCR-1448
URL: https://issues.apache.org/jira/browse/JCR-1448
Project: Jackrabbit
Issue Type: Bug
Components: jackrabbit-ocm
Affects Versions: 1.4
Reporter: Wes Smoak
Problem occurs when both parent and child beans are versionable. Jackrabbit
creates an nt:versionedChild node that is referenced by the parent node,
referencing the childs versionedHistory node of the child. The current OCM
code does not handle this correctly and produces an error: "Node type
'nt:versionedChild' does not match descriptor node type 'nt:unstructured'"
Below is a example code of the problem and a patch that appears to correctly
resolve the problem.
Within ObjectConverterImpl created the below method.
public Node getActualNode(Session session,Node node) throws
RepositoryException
{
NodeType type = node.getPrimaryNodeType();
if (type.getName().equals("nt:versionedChild"))
{
String uuid =
node.getProperty("jcr:childVersionHistory").getValue().getString();
Node actualNode = session.getNodeByUUID(uuid);
String name = actualNode.getName();
actualNode = session.getNodeByUUID(name);
return actualNode;
}
return node;
}
AND modified the following to call the above method
public Object getObject(Session session, Class clazz, String path)
{
try {
if (!session.itemExists(path)) {
return null;
}
if (requestObjectCache.isCached(path))
{
return requestObjectCache.getObject(path);
}
ClassDescriptor classDescriptor =
getClassDescriptor(clazz);
checkNodeType(session, classDescriptor);
Node node = (Node) session.getItem(path);
if (!classDescriptor.isInterface()) {
{
node = getActualNode(session,node);
checkCompatiblePrimaryNodeTypes(session,
node, classDescriptor, true);
}
}
ClassDescriptor alternativeDescriptor = null;
if
(classDescriptor.usesNodeTypePerHierarchyStrategy())
{
if
(node.hasProperty(ManagerConstant.DISCRIMINATOR_PROPERTY_NAME))
{
String className =
node.getProperty(ManagerConstant.DISCRIMINATOR_PROPERTY_NAME
).getValue().getString();
alternativeDescriptor =
getClassDescriptor(ReflectionUtils.forName(className));
}
} else {
if
(classDescriptor.usesNodeTypePerConcreteClassStrategy())
{
String nodeType =
node.getPrimaryNodeType().getName();
if
(!nodeType.equals(classDescriptor.getJcrType()))
{
alternativeDescriptor =
classDescriptor.getDescendantClassDescriptor(nodeType);
// in case we an alternative
could not be found by walking
// the class descriptor
hierarchy, check whether we
would
// have a descriptor for the
node type directly (which
// may the case if the class
descriptor hierarchy is
// incomplete due to missing
configuration. See JCR-1145
// for details.
if (alternativeDescriptor ==
null) {
alternativeDescriptor =
mapper.getClassDescriptorByNodeType(nodeType);
}
}
}
}
// if we have an alternative class descriptor,
check whether its
// extends (or is the same) as the requested class.
if (alternativeDescriptor != null) {
Class alternativeClazz =
ReflectionUtils.forName(alternativeDescriptor.getClassName());
if (clazz.isAssignableFrom(alternativeClazz)) {
clazz = alternativeClazz;
classDescriptor = alternativeDescriptor;
}
}
// ensure class is concrete (neither interface nor
abstract)
if (clazz.isInterface() ||
Modifier.isAbstract(clazz.getModifiers())) {
throw new JcrMappingException( "Cannot
instantiate non-concrete
class " + clazz.getName()
+ " for node " + path + " of type " +
node.getPrimaryNodeType().getName());
}
Object object =
ReflectionUtils.newInstance(classDescriptor.getClassName());
if (! requestObjectCache.isCached(path))
{
requestObjectCache.cache(path, object);
}
simpleFieldsHelp.retrieveSimpleFields(session,
classDescriptor, node, object);
retrieveBeanFields(session, classDescriptor, node,
path, object, false);
retrieveCollectionFields(session, classDescriptor,
node, object, false);
return object;
} catch (PathNotFoundException pnfe) {
// HINT should never get here
throw new
ObjectContentManagerException("Impossible to get
the object
at " + path, pnfe);
} catch (RepositoryException re) {
throw new
org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to
get the object at " + path, re);
}
}
>
>
>
> > I am building a test application against OCM. I have the following
> > classes that are annotated for OCM. The problem is that when I update
> and
> > version the root object PressRelease the Bean Author is versioned to
> > nt:versionedChild. While the OCM is checking for node type
> compatibility
> > it is throwing the following exception. It looks like the
> versionedChild
> > is not handled correctly. Any suggestions?
> >
> > I also attempted to retrieve the version based on the version name for
> the
> > rootVersion but also trapped. From a Version object how should I access
> > each of the versioned entries?
> >
> > Thanks
> > Wes
> >
> > @Node (jcrMixinTypes="mix:versionable")
> > public class PressRelease
> > {
> > @Field(path=true) String path;
> > @Field String title;
> > @Field Date pubDate;
> > @Field String content;
> > @Bean Author author;
> > @Collection (elementClassName=Comment.class) List<Comment>
> comments = new
> > ArrayList<Comment>();
> >
> > public String getPath() {
> > return path;
> > }
> > public void setPath(String path) {
> > this.path = path;
> > }
> > public String getContent() {
> > return content;
> > }
> > public void setContent(String content) {
> > this.content = content;
> > }
> > public Date getPubDate() {
> > return pubDate;
> > }
> > public void setPubDate(Date pubDate) {
> > this.pubDate = pubDate;
> > }
> > public String getTitle() {
> > return title;
> > }
> > public void setTitle(String title) {
> > this.title = title;
> > }
> > public Author getAuthor() {
> > return author;
> > }
> > public void setAuthor(Author author) {
> > this.author = author;
> > }
> > public List<Comment> getComments() {
> > return comments;
> > }
> > public void setComments(List<Comment> comments) {
> > this.comments = comments;
> > }
> >
> >
> > }
> >
> > @Node (jcrMixinTypes="mix:versionable")
> > public class Author {
> >
> > @Field(path=true) String path;
> > @Field String name;
> >
> >
> > public String getName() {
> > return name;
> > }
> > public void setName(String name) {
> > this.name = name;
> > }
> > public String getPath() {
> > return path;
> > }
> > public void setPath(String path) {
> > this.path = path;
> > }
> >
> > }
> >
> > MAIN
> >
> > while (versionIterator.hasNext())
> > {
> > Version version = (Version) versionIterator.next();
> > System.out.println("version found : "+ version.getName() + " -
> " +
> > version.getPath() + " - " +
> > version.getCreated().getTime());
> >
> >
> > if (!version.getName().equals("jcr:rootVersion"))
> > {
> >
> > // Get the object matching to the first version
> > pressRelease = (PressRelease)
> > ocm.getObject("/newtutorial",version.getName());
> >
> >
> > System.out.println("PressRelease title : " +
> pressRelease.getTitle());
> > System.out.println(" author: " +
> > pressRelease.getAuthor().getName());
> > System.out.println(" content: " +
> pressRelease.getContent());
> > List comments = pressRelease.getComments();
> > Iterator iterator = comments.iterator();
> > while (iterator.hasNext())
> > {
> > comment = (Comment) iterator.next();
> > System.out.println("Comment : <" + comment.getData()
> + ">" +
> > comment.getText());
> > }
> > }
> > }
> >
> >
> > CONSOLE
> > version found : jcr:rootVersion -
> >
> /jcr:system/jcr:versionStorage/fc/0b/fd/fc0bfd89-c487-4fbe-930f-d837e5dfed79/jcr:rootVersion
> > - Thu Feb 28 15:54:42 EST 2008
> > version found : 1.0 -
> >
> /jcr:system/jcr:versionStorage/fc/0b/fd/fc0bfd89-c487-4fbe-930f-d837e5dfed79/1.0
> > - Thu Feb 28 15:54:59 EST 2008
> > Exception in thread "main"
> > org.apache.jackrabbit.ocm.exception.ObjectContentManagerException:
> Cannot
> > map object of type 'com..pc.repository.Author'. Node type
> > 'nt:versionedChild' does not match descriptor node type
> 'nt:unstructured'
> > at
> >
> org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl.checkCompatiblePrimaryNodeTypes
> (ObjectConverterImpl.java:552)
> > at
> >
> org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl.getObject
> (ObjectConverterImpl.java:361)
> > at
> >
> org.apache.jackrabbit.ocm.manager.beanconverter.impl.DefaultBeanConverterImpl.getObject
> (DefaultBeanConverterImpl.java:80)
> > at
> >
> org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl.retrieveBeanField
> (ObjectConverterImpl.java:666)
> > at
> >
> org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl.retrieveBeanFields
> (ObjectConverterImpl.java:621)
> > at
> >
> org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl.getObject
> (ObjectConverterImpl.java:309)
> > at
> >
> org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl.getObject(
> ObjectContentManagerImpl.java:313)
> > at com.pc.repository.Main.main(Main.java:345)
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.