JCR Deep Dive
Defining Content
Content in the JCR is by nature defined in a highly-structured format, meaning that individual classes and properties are identified. In object-oriented modeling, structure is expressed via the definition of classes that can be visualized in a UML class diagram. Classes contain member variables and methods and can be instantiated as object. The JCR follows a very similar approach, except that these concepts are named differently:
|
OO-Concept |
JCR Equivalent |
Description |
|
Class |
Node Type |
Defines the structure of the objects to be created. |
|
Object |
Node |
Instance of a node type. |
|
Member Variable |
Property |
The JCR uses primitive types to define properties, much like standard object-oriented programming which uses primitives such as integers and strings also. |
|
Type |
Property Type |
Defines atomic types, such as integers, strings, dates, and pointers (references). |
|
Function |
None |
The JCR does not model functionality, only data. Hence there is no equivalent of a function. |
The JCR further defines a common parent type for nodes and properties, called item. Each workspace in a JCR repository contains any number of items.
A node may reference any number of child nodes as well as any number of property nodes, essentially utilizing the object-oriented composite pattern to build a graph of items where nodes may be internal or leaf elements and properties may only be leaf elements. Each node must have a parent node, meaning there cannot be free-floating, and hence inaccessible, nodes in the repository.

Items, Nodes, Properties
Let’s take a step back and look at this from the birds-eye perspective. The JCR is essentially a flexible storage engine. It uses a schema definition to describe the allowed structure of the individual instances of nodes and properties. As a matter of fact, this schema definition can be provided as a file. It then provides a programmatic API for the developer to create, store, retrieve, and query content within this structure. The biggest leap from traditional object-oriented programming is that the structure is not defined in terms of class definition but as a schema definition file, most likely in written in XML. This schema definition is also referred to as the content model.

Birds-Eye View of JCR
In the JCR, the model is expressed through the concept of node types and property types. Every node must have exactly one node type associated with it. The node type defines the properties each node may reference as well as other characteristics of the node. Nodes can be placed in an inheritance relationship, i.e. the node characteristics include the parent type which properties are inherited from. A node type may also be defined to be abstract (in JSR 283 only), meaning that it cannot be instantiated, i.e. no node instances of this type can be created – it is purely used to implement the object-oriented principle of abstraction.
Nodes may have unique identifiers (a UUID) if they inherit from the built-in base type mix:referenceable. This is, in essence, identical to an object’s identity in standard object-oriented programming languages. As a matter of fact, Reference properties in the JCR simply reference the UUID of a node, meaning that a node may be copied, moved, or renamed without breaking these references. As a consequence, all nodes which may be referenced through such a property must inherit from mix:referenceable. Inheriting from this base type automatically injects a property with the name jcr:uuid into the node type declaration. The method Node.getUUID() is consequently merely a shortcut for Node.getProperty(“jcr:uuid “).getValue().getString().
The JCR defines a pre-set number of property types which are split into two major categories: primitive properties, such as integers and strings, and reference properties which may reference other items in the repository or external URIs. Reference types may enforce the concept of referential integrity, i.e. not break links. This is particularly useful for modeling references of content which is contained within one repository. The content editor may rename, move, delete content and the repository automatically enforces that no references break through these actions. There are numerous trade-offs to be considered when choosing these types which are elaborated in the upcoming chapter on content modeling.
Properties may further be defined to be mandatory or optional.
|
Property Type |
Type |
Summary |
|
String |
Primitive |
A string property |
|
Binary |
Primitive |
A binary large object, or blob. This type is used for storing unstructured data in the repository. Examples include images, css files, flash files, etc. |
|
Date |
Primitive |
A date property |
|
Long |
Primitive |
A long property (64-bit signed two’s complement integer) |
|
Double |
Primitive |
A double property (64-bit IEEE 754 floating point) |
|
Boolean |
Primitive |
A boolean property (true/false) |
|
Decimal* |
Primitive |
Arbitrary length decimal number (maps to java.math.BigDecimal) |
|
Name |
Primitive |
Namespace-qualified string, such as the name of a node type, e.g. as nt:folder or samples:teaser. This can be particularly useful if a property references a content type, such as “all nodes of type samples:teaser in a particular folder“. |
|
Path |
Reference |
Represents a path within the workspace to a particular item (such as /a/b/foo). This reference property does not enforce referential integrity. |
|
Reference |
Reference |
A reference property refers to another node in the workspace via the id of the referenced node. The repository will enforce referential integrity. |
|
WeakReference* |
Reference |
Identical to a Reference property with the exception that referential integrity it not enforced. Accessing a “stale” link will throw an exception. |
|
URI* |
Reference |
Identical to a String property except that it only allows values that conform to the URL syntax (RFC 3986). This is predominantly used for modeling external references, such as web sites. |
|
Undefined |
n/a |
A property of undefined type. The type can be defined at runtime, meaning by the Node.addNode function. Two node instances of the same node type could hence have the same property (by name) with different types. Internally, the JCR stores undefined properties as String values, i.e. they are automatically converted. Implementation-specific issues may arise as a consequence when, for example, storing binary properties in undefined properties. |
*Denotes JSR-283 specific properties
Properties may further be defined to be multi-valued. This is equivalent to defining an array property, i.e. a property that may have more than one value. It is possible to query the node type definition within the API to determine, for example, whether a property is multi-valued as the following example code illustrates:
Node node = session.getNodeByUUID("some existing uuid");
Property property = node.getProperty("sampleProperty");
if (property.getDefinition().isMultiple()) {
// there are potentially multiple values
Value[] values = property.getValues();
} else {
// there is only one value
Value value = property.getValue();
}
Also refer to the CND in a nutshell which outlines the compact node type definition language in-depth.
Namespaces
The repository features native support for namespaces. These namespaces are modeled after XML namespaces and allow different aspects of the content model to be grouped together within them. Namespaces are delimited by a “:” (colon) character. Similar to XML namespaces, the namespace prefix on the left side of the colon is a shorthand notation for the full namespace name, designated by a URI. The JCR defines four built-in namespaces:
| Prefix | URI | Summary |
| Jcr | http://www.jcp.org/jcr/1.0 | Reserved for built-in node types and properties, for example the jcr:uuid property. |
| nt | http://www.jcp.org/jcr/nt/1.0 | Reserved for built-in primary node types, for example nt:file. |
| mix | http://www.jcp.org/jcr/mix/1.0 | Reserved for built-in mixin types, for example mix:referenceable. |
| xml | http://www.w3.org/XML/1998/namespace | Reserved for reasons of compatibility with XML. According to the JSR specification, this prefix should not be used by clients of the API in the names of normal nodes or properties, since doing so will cause problems on export to XML. |
| (empty) | (empty) | The empty namespace is the default namespace. |
In a writeable repository, namespaces can be added via the javax.jcr.NameSpaceRegistry class. The following code registers the samples prefix to the URI http://www.jtoppe.com/samples. Subsequent API calls can now use the samples prefix.
Workspace ws = session.getWorkspace();
// register the samples prefix with the given URI
ws.getNamespaceRegistry().registerNamespace("samples",
"http://www.jtoppe.com/samples");
// use the samples prefix
Node folder = session.getRootNode().addNode("demo", "samples:folder");
Namespaces have to be declared in the repository before they can be referenced through the API or within the node type definition files.
The same hold for the node definition filein which the prefixes used need to be mapped to the URI. Notice that the URI, as the fully qualified identifier, specified in the CND file must match the URI registered via the NameSpaceRegistry.
// CND namespace definitions
Comments
9 Responses to “JCR Deep Dive”
Leave a Reply
9 Responses to “JCR Deep Dive”
Leave a Reply
First, thank you for providing this very informative site. And Secondly, just in case it has not been brought to your attention: the URI links to the http://www.jcp.org/ site are out of date (used in section 3. Defining Content).
Regards
Duncan Reade
Thanks for that great post.
It seems node type folder is missing?
Really good post.. thanks for the effort
Hi, great article.
But as Thomas said previously, it seems you forgot to put the node type “samples:folder” definition. It seems it’s a copy/paste of the “samples:content” definition instead.
Really great article.
With regards to the missing definition for samples:folder, I believe the below works.
[samples:folder] > samples:content
// accept any subnodes of type samples:content
+ * (samples:content) multiple
I adapted this from the example in the CND in a nutshell section of this blog.
Thanks! I need to spend some time updating my blog at some point :-)
Great content. Are there some good interative builder for CND Types ? Would be interesting links
Building an interactive builder shouldn’t be that hard. Back when I worked for CoreMedia we had a tool that would take the XMI from any old UML tool and XSLT’ed it to a content definition file. Wasn’t CND but XML, but same idea.
Java Content Repository Deep Dive…
I found an interesting “article” online about Java Content Repositories (JCR). I’m going to look into this further because it may be useful as a replacement to our current JPA workflow. JCR supports many features that should be useful,……