Friday, May 22, 2009

Jackrabbit/JCR Versioning FAQ

There is not a lot of documentation about Jackrabbit/JCR versioning around. So I thought I could publish a little FAQ about JCR versioning.


How do I make a Node versionable?
node.addMixin(JcrConstants.MIX_VERSIONABLE);

How to get the current Version of a Node?
node.getBaseVersion();

How do I increment the minor version of a Node?
node.checkout();
node.setProperty("title", new StringValue("test"));
getSession().save();
node.checkin();


How do I increment the major version of a Node?
You can't, simple as that.
http://osdir.com/ml/apache.jackrabbit.devel/2005-10/msg00417.html

How to restore a node?
node.checkout();
node.setProperty("title", new StringValue("test 2"));
getSession().save();
Version lastVersion = node.checkin();

node.checkout();
node.setProperty("title", new StringValue("test 3"));
getSession().save();
node.checkin();

System.out.println("CURRENT: " + node.getProperty("title").getValue().getString());
node.restore(lastVersion, true);
System.out.println("RESTORED: " + node.getProperty("title").getValue().getString());

The output will be:
CURRENT: test 3
RESTORED: test 2

How do I iterate over all versions of a Node?
VersionIterator i = node.getVersionHistory().getAllVersions();
i.skip(1); // important, otherwise the currentNode will fail to read the 'title' property
while (i.hasNext()) {
Version v = i.nextVersion();
NodeIterator nodeIterator = v.getNodes();
while (nodeIterator.hasNext()) {
Node currentNode = nodeIterator.nextNode();
System.out.println("Version: " + v.getName());
System.out.println(currentNode.getProperty("title").getValue().getString());
}
}

Do I have to add JcrConstants.MIX_VERSIONABLE to my subnodes?
No, changed subnodes are correctly stored under the version of the versionable Node.

Node node = root.addNode(name);
node.addMixin(JcrConstants.MIX_VERSIONABLE);
node.setProperty("title", new StringValue("test 1"));
Node subnode = node.addNode("subnode");
subnode.setProperty("descr", "this is a description");
getSession().save();
node.checkin();

node.checkout();
subnode = node.getNode("subnode");
subnode.setProperty("descr", "this is a NEW description");

node.setProperty("title", new StringValue("test 2"));
getSession().save();
node.checkin();

VersionIterator i = node.getVersionHistory().getAllVersions();
i.skip(1);
while (i.hasNext()) {
Version v = i.nextVersion();
NodeIterator nodeIterator = v.getNodes();
while (nodeIterator.hasNext()) {
Node currentNode = nodeIterator.nextNode();
System.out.println("Version: " + v.getName());
System.out.println(currentNode.getProperty("title").getValue().getString());
if (currentNode.hasNodes()) {
for (NodeIterator childs = currentNode.getNodes(); childs.hasNext();) {
Node child = childs.nextNode();
System.out.println("Description: " + child.getProperty("descr").getValue().getString());
}
}
}
}


OUTPUT:
Version: 1.0
test 1
Description: this is a description
Version: 1.1
test 2
Description: this is a NEW description

How can I export a Node and all it's Versions?
That's not possible.

If I delete a Node will it's history be deleted as well?
No you have to iterate over the versions and call VersionHistory.removeVersion(String versionName);

Usefull links:
http://www.onjava.com/pub/a/onjava/2006/10/04/what-is-java-content-repository.html?page=1
http://jcp.org/en/jsr/detail?id=170

5 comments:

Penguin Fan said...

It is very useful article about JCR versioning.

Here I have two questions for you. (1)What do you mean by version number? JCR version object has getUUID() method to return an unique id. (2) I am uploading files. We need the files versioned. We also needs the ability to view old versions of a file. I am thinking using to use version uid to resolve file versions, but haven't get through. Do you have any suggestions? Thanks a lot.

Thrillaholic said...

I am looking to do the same. In sorts I would like parts of the workspace to act as an CMS with versioning, merging and such for the files being stored. From what I can see in the spec the versioning deals well with basic nodes that do not store binary/files as properties.

Thanks

Akram Ben Aissi said...

Very usefull indeed. Thanks for compiling these information. Howto's about JCR a pretty rare on the internet.

By the way, how do you find these informations ? Reading the spec/API ?

Flavio Donzé said...

Since I didn't find enough documentation I just wrote some code and tested the result.

About a month ago I removed Jackrabbit from our software and implemented a simple Repository myself (data store and versioning). One of the main reason was the lack of documentation.

Akram Ben Aissi said...

I really do agree: Jackrabbit suffers from a lack of documentation.
I turned to modeshape a few weeks ago.
www.jboss.org/modeshape