JC-Rest: RESTful JCR Services & Repository Browser

I’m happy to announce the initial release of JC-Rest. This is an application that provides a set of RESTful services for accessing content in a JCR repository. These services can return XML, JSON, ATOM, or even HTML via custom FreeMarker templates.

Back in June I wrote a post that talked about building RESTful services using CXF (JAX-RS), Spring, Spring Modules (JCR), and the JCR API. To sum it up, I was working with a client who was using CQ. It didn’t take long before several other applications all required access to the CQ content. Since CQ doesn’t provide an easy means to do this, I wrote a set of highly customized services to return the content. The services were written to meet the requirements of each individual client application that required specific content.

When all was said and done, I realized there was quite a bit of redundancy. Not only technically, but logically as well. I came to the conclusion that it would have been better to build a smaller set of abstract, generalized services. And then perhaps allow for some customization on top them. That is what led me to build JC-Rest.

It is just in its infancy. I hope that others can find some value in it.

I’ve been asked why bother considering the emergence of Sling. Well, this was started before I became familiar with Sling. Even so, it is not intended to compete with Sling or anything else. It is meant as an auxiliary application to those such as CQ, Magnolia, Jackrabbit and so on. If you are using Sling, then you might not have a need for JC-Rest. On the other hand, if you are using a web content management system then you might find some value in it. Even if you have just a Jackrabbit based application, you might still find some value in it. The primary purpose of JC-Rest is to expose JCR content to other applications in a RESTful fashion.

First Example

First, lets take a look at the objects returned. There are only two: node and property.

Here is an example of the root of a CQ repository.

/jc-rest/services/path/nodes/content?
includeAllProperties=true 

<content> 
-<node parent="/" name="content"> 
--<nodes/> 
--<properties> 
---<property> 
----<name>cq:uuid</name> 
----<type>String</type> 
----<value>31535209-4d36-3e48-bceb-9cc4e82722b0</value> 
---</property> 
---... 
--</properties> 
-</node> 
</content> 

A few more examples…

Now lets take a few examples from a made up repository. Here is the structure. 

company 
--en 
----products 
------books 
--------book1 (@title=This Book, @price=9.99) 
----------content (primary item) 
------------review1 
------------review2 
--------book2 (@title=That Book, @price=9.99) 
----------content (primary item) 
------magazines 
--------mag1 (@title=This Mag, @price=5.99) 
----------content (primary item) 
--------mag2 (@title=That Mag, @price=4.99) 
----------content (primary item) 
------------review3 
------------review4 

/nodes/content/company/en/products?
nodeDepth=2&nodeType=my:product 

This would return the two products category nodes, books & magazines, without any child nodes or properties. 

/nodes/content/company/en/products?
nodeDepth=3&nodeType=my:product 

This would return all of the product nodes (all the books and magazines) without any child nodes or properties. 

/nodes/content/company/en/products?
nodeDepth=3&nodeType=my:product&propertiesToShow=title

This would return the same as the previous example, but would include the title property for each product node.

/nodes/content/company/en/products?
nodeDepth=3&nodeType=my:product&includeAllProperties=true 

This would return the same as the previous example, but would include all of the properties (title and price) for each product node. 

/nodes/content/company/en/products?nodeDepth=2&nodeType=my:product&includeAllProperties=true&includePrimaryItem=true 

This would return the same as the previous example, but would include the content node for each product node returned. 

/nodes/content/company/en/products?nodeDepth=2&nodeType=my:product&includeAllProperties=true&includePrimaryItem=true&includePrimaryItemDescendants=true 

This would return the same as the previous example, but would include the content node for each product node returned along with all the review nodes beneath it.

There are also services for returning ATOM feeds, HTML, and events (as opposed to nodes).

Repository Browser

I also created a lightweight JCR repository browser. If you go to the index page (/jc-rest) there are two links. One is to a lightweight repository browser I built using JC-Rest and YUI (/jc-rest/browser.html). The other is an HTML based FreeMarker repository browser. 

Repository browser

Repository browser

Check it out! JC-Rest (Google Code)

So until next time, good fight, good night.