Each node in a Jackrabbit workspace tree has a node type that defines the child nodes and properties it may (or must) have. Developers can use node types to define a custom content model for their application domain and have Jackrabbit enforce the constraints of that model at the repository level.
There are two categories of node types, primary and mixin. Every node has a primary node type assigned to it upon creation (see Node.addNode in the JCR API). In addition, a mixin node type may be added to a node later in its lifecycle (see Node.addMixin).
The primary node type of a node usually defines node structure (i.e., allowed and required child nodes and properties) related to the problem domain being modeled. For example, a node used in storing content about business contacts might have the primary type myapp:Contact which defines properties such as myapp:givenName, myapp:familyName and so forth.
Mixin node types usually specify additional properties or child nodes related to a capability being added to the node. These capabilities may include generic repository-level functions as in the case of the built-in mixins mix:versionable and mix:lockable, for example, or domain-level capabilities such as a (hypothetical) myapp:Emailable mixin type that adds the property myapp:emailAddress to a node.
Primary node types are arranged in an inheritance hierarchy. Every primary node type must be the subtype of at least one existing node type. The built-in node type nt:base serves as the root of this hierarchy. Jackrabbit supports multiple inheritance of node types so node types can have more than one supertype.
Mixin node types do not have to have supertypes.
The JSR 170 specification and the current public review draft of the JSR 283 specification (section 4.7.7) leave it up to the implementation whether e.g. the orderable child nodes setting is inherited from supertypes. Inheritance semantics, especially with multiple inheritance, are non-trivial at best and up to a certain degree arbitrary. Jackrabbit therefore, in compliance with the spec, doesn't support inheritance of node type attributes such as orderable.
A node type definition has the following attributes:
- Name Every node type registered with the repository has a unique name. The naming conventions for node types are the same as for items (i.e., they may have a colon delimited prefix).
- Supertypes A primary node type (with the exception of nt:base) must extend another node type (and may extend more than one node type). A mixin node type may extend another node type.
- Mixin Status A node type may be either primary or mixin.
- Orderable Child Nodes Status A primary node type may specify that child nodes are client-orderable. If this status is set to true, then Node.orderBefore can be used to set the order of child nodes. Only primary node types control a node's status in this regard. This setting on a mixin node type will not have any effect on the node.
- Property Definitions A node type contains a set of definitions specifying the properties that nodes of this node type are allowed (or required) to have and the characteristics of those properties (see below).
- Child Node Definitions A node type contains a set of definitions specifying the child nodes that nodes of this node type are allowed (or required) to have and the characteristics of those child nodes (including, in turn, their node types, see below).
- Primary Item Name A node type may specify one child item (property or node) by name as the primary item. This indicator is used by the method Node.getPrimaryItem().
A property definition (within a node type definition) contains the the following information:
- Name The name of the property to which this definition applies, or "*" if this definition is a "residual definition', meaning that it applies to any additional properties with any names apart from those otherwise defined in this node type.
- Required Type The required type of the property. One of
- UNDEFINED (the property can be of any type)
- Value Constraints The value constraints on the property define the range of values that may be assigned to this property.
- Default Value The value that the property will have if it is auto-created.
- Auto-create Status Whether this property will be auto-created when its parent node is created. Only properties with a default value can be auto-created.
- Mandatory Status A mandatory property is one that must exist. If a node of a type that specifies a mandatory property is created then any attempt to save that node without adding the mandatory property will fail. Since single-value properties either have a value or do not exist (there being no concept of the null value) this implies that a mandatory single-value property must have a value. A mandatory multi-value property on the other hand may have zero or more values.
- On-Parent-Version Status The onParentVersion status of specifies what happens to this property if a new version of its parent node is created (i.e. a checked-in is done on it).
- Protected Status A protected property is one which cannot be modified (i.e. have child nodes or properties added or removed) or removed from its parent through the JCR API.
- Multiple Values Status Whether this property can have multiple values, meaning that it stores an array of values, not just one. Note that this "multiple values" flag is special in that a given node type may have two property definitions that are identical in every respect except for the their "multiple values" status. For example, a node type can specify two string properties both called X, one of which is multi-valued and the other that is not. An example of such a node type is nt:unstructured.
A child node definition (within a node type definition) contains the the following information:
- Name The name of the child node to which this definition applies or "*" if this definition is a "residual definition', meaning that it applies to any additional child nodes with any names apart from those otherwise defined in this node type.
- Required Primary Types If it specifies only a single node type N then the primary node type of this child node must be N or a subtype of N. If this attribute specifies multiple node types N1, N2,..., Nm then the primary node type of this child node must be a subtype of all the types N1, N2, ... Nm. Note that this is possible because Jackrabbit supports multiple inheritance among node types and that each node still has one and only one primary node type.
- Default Primary Type This is the primary node type automatically assigned if no node type information is specified when the node is created.
- Auto-create Status Governs whether this child node will be auto-created when its parent node is created.
- Mandatory Status Governs whether the child node is mandatory. A mandatory child node is one that must exist. If a mandatory child node is missing from a parent node then save on the parent node will fail.
- On-Parent-Version Status This specifies what to do with the child node if its parent node is versioned.
- Protected Status This governs whether the child node is protected. A protected node is one which cannot be modified (have child node or properties added to it or removed from it) or be removed from its parent through the JCR API.
- Same-Name Siblings Status This governs whether this child node can have same-name siblings, meaning that the parent node can have more than one child node of this name.
Each Jackrabbit instance has a NodeTypeRegistry which is created on start-up and populated with the set of built-in node types (these include both those required by the JCR specification and others required by the Jackrabbit implementation).
First you define your node types in a text file using the "Compact Namespace and Node Type Definition" (CND) notation, then register them using the JackrabbitNodeTypeManager. The following code gives an example: