jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Brian Thompson" <elephant...@gmail.com>
Subject Re: How to start thinking in JCR
Date Tue, 03 Apr 2007 18:11:09 GMT
In your CND-file, you need to declare all the namespaces you'll use, even
the ones that come with Jackrabbit:

==============================

/* orig.namespaces */
<mix = 'http://www.jcp.org/jcr/mix/1.0'>
<nt = 'http://www.jcp.org/jcr/nt/1.0'>

/* my stuff */
<my = 'http://www.example.com/jcr-ns/my'>

<page = 'http://www.example.com/jcr-ns/page'>

[my:page] > nt:unstructured, mix:referenceable
        orderable
        - my:active (boolean) = 'true' mandatory autocreated

=======================

etc...


On 4/2/07, Nandana Mihindukulasooriya <nandana.cse@gmail.com> wrote:
>
> Hi,
>      I changed the Node structure as following according to the discussion
> and tried to register them in the repository. Here are some of the
> problems
> I came across.
>
> Grammer for CND notation defines a property of a Node type as
>
> property_def ::= "-" property_name [property_type_decl]
>                  [default_values] [attributes]
>                  [value_constraints]
> property_name ::= string
>
> Does all properties have to have a namespace prefix ? When I tried
> to register the node types using the CompactNodeTypeDefReader it
> gave an error caused by "UnknownPrefixException".
>
> It also said that if I define the autocreated attribute for a childnode
> I should define the default type for them which is of cource reasonable.
>
> Like Node class's hasNode() method is there convinient methods to check
> whether a namespace prefix is already registered ? and to check whether
> a Node Type is already registed ? I didn't find such methods in
> NodeTypeManager or NamespaceRegistry Interfaces of JCR. I used the
> NodeTypeManagerImpl which inplements the JackrabbitNodeTypeManager
> Interface.
>
> But in the mailing list
> // only register the type if it does not yet exist
>     if (!manager.hasNodeType("myfile"))
> is used to check this. Is that method not available in Jackrabbit 1.0 ?
>
> To create a the repository I used the TransientRepository class which
> created
> me a default repository configuration file. But if I am using JNDI binding
> do I have to create a repository.xml by my self ? Is there a way to
> specify
> to
> create a default configuration ?
>
> Where can I find contrib/compact-nt tools ?
>
> I really appreciate your comments. Thank you in advance.
>
> BR,
> Nandana
>
>
> ----------------------------------------------------- Node Structure
> -------------------------------------------------------
>
> /blogRoot [nt:folder]
> /blogRoot/user [blog:user]
> /blogRoot/user/blogSpace [nt:folder]
> /blogRoot/user/blogSpace/<yyyy> [nt:folder]
> /blogRoot/user/blogSpace/<yyyy>/<mm> [nt:folder]
> /blogRoot/user/blogSpace/<yyyy>/<mm>/blogEntry [blog:blogEntry]
> /blogRoot/user/blogSpace/<yyyy>/<mm>/blogEntry/comment [blog:Comment]
> /blogRoot/user/library [nt:folder]
> /blogRoot/user/libray/avatar [nt:file]
> /<libray> [nt:folder]
>
> -------------------------------------------   CND Notation for custom
> types   -------------------------------------
>
>
> <blog = 'http://jackrabbit.apache.org/jackrabbit-jcr-demo/1.0'>
> <nt =  ... >
> <jcr =  ... >
>
>
> [blog:user] > mix:referenceable
> - blog:nickname  (string) mandatory
> - blog:email  (string) mandatory
> - blog:password (string) mandatory
> + blog:library (nt:folder) =nt:folder mandatory autocreated
> + blog:blogSpace (nt:folder) =nt:folder mandatory autocreated
>
>
> [blog:blogEntry] > nt:hierarchyNode, mix:referenceable
> - blog:title (string) mandarory primary
> - blog:content (string) mandatory
> - blog:rate (long)
> + blog:attachments (nt:folder) =nt:folder mandatory autocreated
>
> [blog:comment]
> - blog:content (string) mandatory primary
> - blog:commenter (reference ) mandatory  < blog:user
>
> -----------------------------------------------------------   Stack trace
> -----------------------------------------------------
>
> org.apache.jackrabbit.core.nodetype.compact.ParseException: Error while
> parsing 'nickname'
>     at org.apache.jackrabbit.core.nodetype.compact.Lexer.fail(Lexer.java
> :146)
>     at
>
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader.toQName
> (CompactNodeTypeDefReader.java:635)
>     at
>
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader.doPropertyDefinition
> (CompactNodeTypeDefReader.java:373)
>     at
>
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader.doItemDefs
> (CompactNodeTypeDefReader.java:331)
>     at
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader.parse
> (
> CompactNodeTypeDefReader.java:208)
>     at
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader
> .<init>(CompactNodeTypeDefReader.java:165)
>     at
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader
> .<init>(CompactNodeTypeDefReader.java:150)
>     at nandana.jackrabbit.example1.NodeStructure.RegisterCustomNodeTypes(
> NodeStructure.java:94)
>     at nandana.jackrabbit.example1.NodeStructure.main(NodeStructure.java
> :58)
> Caused by: org.apache.jackrabbit.name.UnknownPrefixException:
>     at org.apache.jackrabbit.name.QName.fromJCRName(QName.java:596)
>     at
>
> org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader.toQName
> (CompactNodeTypeDefReader.java:630)
>     ... 7 more
> Exception in thread "main" java.lang.NullPointerException
>     at nandana.jackrabbit.example1.NodeStructure.RegisterCustomNodeTypes(
> NodeStructure.java:101)
>     at nandana.jackrabbit.example1.NodeStructure.main(NodeStructure.java
> :58)
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> On 3/28/07, Jukka Zitting <jukka.zitting@gmail.com> wrote:
> >
> > Hi,
> >
> > On 3/29/07, Nandana Mihindukulasooriya <nandana.cse@gmail.com> wrote:
> > > I should thank Brian, Xin and Jukka a lot for their valuable feedbacks
> > > and I was able to understand lot of things when I went through the
> > > JSR-170 again after reading the feedbacks.
> >
> > Excellent, thanks again for your efforts. Comments below...
> >
> > > Now we will create users using their unique user IDs like
> > >
> > > Node root = session.getRootNode();
> > > Node user = root.addNode("uniqueUserID","blog:user");
> > >
> > > To avoid uniqueUserID conflit with other root's child nodes ( which
> are
> > not
> > > user nodes), can we use a namespace prefix as "id:uniqueID" with <id =
> > > http://... >.
> >
> > Namespaces are a good way to avoid naming conflicts, but in this case
> > an even better way would be to create your own "application root node"
> > like /blog:root like the one you propose below. Such a root node
> > nicely separates the blog content from any other application you may
> > want to store in the same workspace. It also makes it easy to limit
> > searches to just that subtree instead of including for example the
> > whole /jcr:system tree.
> >
> > Also, I would encourage you to use a username or even the real name of
> > the user as the node name instead of a numeric or some other abstract
> > identifier.
> >
> > Thus the code would be:
> >
> >     Node root = session.getRootNode().getNode("blog:root");
> >     Node user = root.addNode(username,"blog:user");
> >
> > > can we add something like this to root node to avoid non-unique
> userIDs
> > ?
> > >
> > >     ChildNodeDefinition
> > >     Name *
> > >     RequiredPrimaryTypes UNDEFINED
> > >     ...
> > >     SameNameSiblings false
> >
> > The root node definition in Jackrabbit is essentially equivalent to
> > nt:unstructured, so you can already add whatever child nodes you want
> > to it without modifying the type definition.
> >
> > > If we can, how can we define it ? and is ItemExistsException throwed
> > > immediately or on save in jackrabbit implementation of jcr ?
> > > If we can't is there any other way to prevent it ?
> >
> > Node types can be registered using the CND or XML node type definition
> > formats and the JackrabbitNodeTypeManager extension interface found in
> > the jackrabbit-api component.
> >
> > Generally you shouldn't rely on an JCR implementation to perform
> > consistency checks before the save() call. There are even many full
> > consistency checks that can logically not be performed before the
> > save() call.
> >
> > > or can I make a one root note child like this and define it not to
> have
> > > sameNameSiblings.
> > >
> > > [blog:blog]
> > >     - * [blog:user]
> > >     - library [nt:folder] mandatory autocreated
> >
> > Such an approach would be my preferred alternative. You can't easily
> > constraint the repository root node not to have children with same
> > names, but you can quite easily enforce that in your application.
> >
> > As to the blog:blog node type, again I would prefer the standard
> > nt:folder type. I'd also place the image library under a separate
> > "content root" since it could very well be used by other applications
> > as well. The content tree would look something like this:
> >
> >     /blog:blog [nt:folder]
> >     /blog:blog/...
> >     /blog:library [nt:folder]
> >     /blog:library/...
> >
> > You can initialize your application like this (assuming you've already
> > set up the namespaces):
> >
> >     Session session = ...;
> >     Node root = session.getRootNode();
> >     if (!root.hasNode("blog:blog")) {
> >         root.addNode("blog:blog", "nt:folder");
> >     }
> >     if (!root.hasNode("blog:library")) {
> >         root.addNode("blog:library", "nt:folder");
> >     }
> >     session.save();
> >
> > > As blogspace is of type nt:folder which has a child node definition,
> > >
> > >     ChildNodeDefinition
> > >     Name *
> > >     RequiredPrimaryType[nt:hierarchyNode]
> > >
> > > it can in turn have children of type nt:folder as nt:folder is
> > a  subtype of
> > > nt:hierarchyNode. So both <yyyy> and <mm> would be nodes of type
> > nt:folder.
> >
> > Exactly.
> >
> > > So we can use,
> > >
> > > Node blogSpace = user.getNode("blogSpace");
> > > Node year = blogspace.addNode("2007","nt:folder");
> > > Node month = year.addNode("03","nt:folder");
> > >
> > > Is there a way to create a node with intermediate created
> automatically
> > ?
> > > If there is a way, how can we declare the types of intermediate nodes
> ?
> > > Javadoc says it throws a PathNotFoundException if we try to create a
> > > node without creating intermediate nodes.
> >
> > There's no such way, you need to handle that in your application.
> >
> >     Node blogSpace = ...;
> >     if (!blogSpace.hasNode("year")) {
> >         blogSpace.addNode("year", "nt:folder");
> >         blogSpace.save();
> >     }
> >     Node year = blogSpace.getNode("year");
> >     if (!year.hasNode("month")) {
> >         year.addNode("month", "nt:folder");
> >         year.save();
> >     }
> >     Node month = year.getNode("month");
> >
> > Note that the above code has a slight chance of race conditions if two
> > sessions attempt to create the same intermediate nodes at the same
> > time. You can either proactively prevent it by making the blogSpace
> > node lockable and using JCR locks, or you can catch the concurrent
> > modification exception and recover by retrying the operation. Since
> > the chance of collisions is so small, I would go with the latter
> > option.
> >
> > > So we have to come with a way to name the blog entries. Title may not
> be
> > a
> > > good candidate because they may white spacses and '.', '/', ':', '[',
> > ']', '*',
> > > ''', '"' charactors. Would a simple sequential numbering work ? Is
> there
> > a better
> > > way to handle this ?
> >
> > Generally a somewhat meaningful name is preferred over a sequence
> > number. It makes administration much easier and also gives a nice
> > URL-to-path mapping for web applications. I would go for a solution
> > that either allows the user to specify the node name or uses a
> > "simplifies" title as the node name. Many existing blog applications
> > (for example WordPress) already use a "simplification" algorithm that
> > turns title strings into valid URL path components. A similar solution
> > would be perfect here as well.
> >
> > You would still store the full title as a normal string property to
> > avoid losing data.
> >
> > > Node blogEntry = month.addNode("01","blog:blogEntry");
> > > blogEntry.setProperty("content","my first blog entry");
> > >
> > > As blogEntry is a subtype of nt:hierarchyNode, I would be able to use
> > > jcr:created property to get the created date of the blog.
> >
> > Exactly.
> >
> > > To add an image attachment,
> > >
> > > Node attachments = blogEntry.getNode("attachments");
> > > Node linkedFile = attachments.addNode("attachment01","nt:linkedFile");
> > > linkedFile.setProperty("jcr:content",root.getNode("library/xxx/yyy"));
> > >
> > > jcr:content property of the  nt:linkedFile  type  is of type
> reference.
> >
> > Perfect. Note that the jcr:content reference of an nt:linkedFile node
> > should probably point to the jcr:content resource node of another file
> > instead of the file node itself.
> >
> > > To add a Comment
> > >
> > > Node comment = blogEntry.addNode("01","blog:comment");
> > > comment.setProperty("content","my first comment");
> > > comment.setProperty("commenter", root.getNode("commenterID"));
> >
> > Exactly.
> >
> > > To add a avator to a user,
> > >
> > > Node library = root.getNode("library");
> > > Node manAvatar = library.addNode("manAvator","blog:avatar");
> > > Node content = manAvatar.getNode("jcr:content");
> > > content.setProperty("image",imageInputStream);
> > >
> > > user.setProperty("avatar",manAvator);
> >
> > I think you'd be better of again using the standard nt:hierarchyNode
> > model here instead of custom types. I would define a "personal
> > library" folder for each user and place the avatar image there as
> > either a local nt:file or as a nt:linkedFile that refers to some image
> > in the global image library. A reserved name would be used for the
> > avatar image, but other files could also be stored in this personal
> > library folder. Using the standard node types allows you for example
> > to use the existing WebDAV servlet classes from jackrabbit-jcr-server
> > to serve the content in a web application. As an extra bonus you'd
> > even get PUT support for free for remote clients to update the
> > content!
> >
> >     [blog:user]
> >     ....
> >     + library (nt:folder) mandatory autocreated
> >
> > Adding a custom avatar would be:
> >
> >     Node user = ...;
> >     Node library = user.getNode("library");
> >     Node avatar = library.addNode("avatar", "nt:file");
> >     avatar.addNode("jcr:content", "nt:resource");
> >     avatar.setProperty("jcr:content/jcr:mimeType", "image/gif");
> >     avatar.setProperty("jcr:content/jcr:lastModified",
> > Calendar.getInstance());
> >     avatar.setProperty("jcr:content/jcr:data", ...);
> >     library.save();
> >
> > Adding a standard avatar from the global image library would be:
> >
> >     Node standardAvatar = ...;
> >     Node user = ...;
> >     Node library = user.getNode("library");
> >     Node avatar = library.addNode("avatar", "nt:linkedFile");
> >     avatar.setProperty("jcr:content", standardAvatar.getNode
> > ("jcr:content"));
> >     library.save();
> >
> > > jcr:content is of type nt:base and how can we define that it has a
> > property
> > > "image" which contains Binary data. Or shall I directly add "image"
> > property
> > > to blog:avator type like
> > >
> > > [blog:avatar] > nt:file,mix:referenceable
> > > - image (binary) mandatory primary
> >
> > No. You should instead use the standard nt:resource type as the
> > jcr:content node of a file and store the image data as
> > jcr:content/jcr:data as shown above.
> >
> > If you want to, you can extend the nt:resource type to contain
> > image-specific information like size and possible thumbnails:
> >
> >     [blog:image] > nt:resource
> >     - width (long)
> >     - height (long)
> >     + thumbnails (nt:folder)
> >
> > BR,
> >
> > Jukka Zitting
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message