jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Nandana Mihindukulasooriya" <nandana....@gmail.com>
Subject Re: How to start thinking in JCR
Date Tue, 03 Apr 2007 02:47:43 GMT
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