Monday, November 29, 2010

Sling gotcha

A content-driven application normally implements the basic CRUD operations. Using Sling this should be done relatively easy.
As part of the Read operation you normally have to implement some listing of available resources. Being familiar with JCR API  it would be natural to do it with this JavaScript code in your ESP page

var iter = currentNode.getNodes();
while (iter.hasNext()) {
    var childNode = iter.nextNode();
    ...


Yes, but no! The result is a big fat exception

org.mozilla.javascript.EcmaError: TypeError: hasNext is not a function, it is org.mozilla.javascript.Undefined. (/apps/catalog/html.esp#11)


Hm! currentNode is a JCR Node so getNodes() should return a javax.jcr.NodeIterator which is a java.util.Iterator. So the code looks correct but somehow iter here is not a Java object at all.

I struggled with this several hours. I was very puzzled to see similar code in espblog sample working just fine. The only difference is that espblog uses QueryResult.getNodes() which still returns NodeIterator.

Finally I found the answer in this thread. It turns out Sling wraps Node.getNodes() to return a JavaScript object which has one property for each child node. Probably the idea was to easily iterate over that object with a for-each loop

for each (var childNode in  currentNode.getNodes()) {
    ...


Another solution is to use the property name instead of the getter method

var iter = currentNode.nodes;
while (iter.hasNext()) {
    var childNode = iter.nextNode();
    ...


This seems to circumvent the wrapping done by Sling.

This example illustrates a cute feature of Rhino which allows easy access of JavaBeans properties.

Yes, server side JavaScript can be fun.

1 comment:

  1. I have to thank you sooooo much for posting this information! I just ran into this issue today, and could not find ANYTHING on it until I stumbled onto this post. I started trying every method with Node to try and debug the problem. It's not documented anywhere that I can find, and I don't know how you found the solution to the issue, but I can't thank you enough! :-)

    ReplyDelete