0

I have a SlingServlet that implements a JSON query service (very similar to the AEM Query Builder servlet). It creates a SyntheticResource to respond with a JSP "view", which is the JSON to be served. This JSP uses a to include each result object, which are cq:Page nodes.

When the tries to include a node which can not be rendered, it results in a 400 error, but in a peculiar way. The error appears first, followed by the expected JSON (which is malformed, because the value that could not be included is missing). I am able to override the 400 error text, so as to return "null", but I can not get the error to appear inline.

Consider:

response.api.json.jsp

{
    "metadata": {
                "page": ${pageIndex},
    },
    "data": [
        <% 
            String[] results = (String[])slingRequest.getAttribute("results");
            int i = 0;

            if (results != null) {
                for (String path : results) { 
                    if (i > 0) {
        %>
                        ,
        <%
                    }
        %>
                    <sling:include path="<%=path%>"/>
        <% 
                    i++;
                } 
            }
        %>
    ]
}

the current response

<400.jsp error message up here>
{
    "metadata": {
        "page": 0,
    },
    "data": [
        ,              // <- failed to include the path
        {
            "key1": ,  // <- failed to include the value string/object/etc
            "key2": "value2"
        }
    ]
}

the expected response

{
    "metadata": {
        "page": 0,
    },
    "data": [
        <400.jsp error message>,    // <- failed to include the path
        {
            "key1": <400.jsp error message>,  // <- failed to include the value string/object/etc
            "key2": "value2"
        }
    ]
}

the expected response (assuming 400.jsp contains only "null")

{
    "metadata": {
        "page": 0,
    },
    "data": [
        null,    // <- failed to include the path
        {
            "key1": null,  // <- failed to include the value string/object/etc
            "key2": "value2"
        }
    ]
}

Is there any way to get the error page (400.jsp) to appear inline, so that I can return null?


More info

response.api.json.jsp (main "view" for the service response)

{
    "metadata": {
                "page": ${pageIndex},
    },
    "data": [
        <% 
            String[] results = (String[])slingRequest.getAttribute("results");
            int i = 0;

            if (results != null) {
                for (String path : results) { 
                    if (i > 0) {
        %>
                        ,
        <%
                    }
        %>
                    <sling:include path="<%=path%>"/>
        <% 
                    i++;
                } 
            }
        %>
    ]
}

page/api.json.jsp (data[] nodes included by the response.api.json.jsp)

{
    "uid":              <%=getFormattedString("jcr:uuid", properties)%>,
    "pageTitle":        <sling:include path="pageTitle"/>, // text component
    "body":             <sling:include path="body"/> // parsys component
}

text/api.json.jsp (pageTitle node included by each page/api.json.jsp)

{
    "text":             <%=getFormattedString("text", properties)%>,
    "lastModified":     <%=getFormattedDate("jcr:lastModified", properties)%>,
    "resourceType":     <%=getFormattedString("sling:resourceType", properties)%>
}

parsys/api.json.jsp (body node included by each page/api.json.jsp)

{
    "resourceType":     "${properties['sling:resourceType']}",
    "children": [
        <%
        NodeIterator children = currentNode.getNodes();
        int i = 0;
        if (children != null && children.getSize() > 0) {
            while (children.hasNext()) {
                Node child = children.nextNode();
                if (i > 0) {
        %>
                ,
        <%
                }
        %>
                <sling:include path="<%=child.getPath()%>"/> // any component resource type
        <%
                i++;
            }
        }
        %>
    ]
}
Dave Hughes
  • 352
  • 4
  • 21

1 Answers1

0

Don't use sling:include to get content from the paths, this will raise some recursion selector error. You should read the message node from the paths to get appropriate content value for your json. Here is an example. You can replace "/content/geometrixx-outdoors/en/women/jcr:content/par/banner" with your path.

<%@ include file="/libs/foundation/global.jsp" %>
<%@ page session="false" import="org.apache.sling.api.resource.Resource" %>
<%@ page session="false" import="javax.jcr.Node" %>
<%
      String yourMessage = "";
try {
      Resource rs = resourceResolver.getResource("/content/geometrixx-outdoors/en/women/jcr:content/par/banner");
    if (rs != null) {
        Node node = rs.adaptTo(Node.class);
        if (node.hasProperty("yourContentNode")) {
            yourMessage = node.getProperty("yourContentNode").getString();
        }

    }

} catch (Exception e) {

}

%>

{
    "metadata": {
                "page": 1,
    },
    "data": [
        <%= yourMessage %>,
        {
            "key1": "value 1", 
            "key2": "value2"
        }

    ]
}
Tien Nguyen
  • 4,298
  • 9
  • 30
  • 44
  • Thank you, but this is a completely different solution from the current JSP-driven implementation that we already have. If the responses were a single level, I would be inclined to go with your solution, but we have nested data. For example, each page included in data[] has an object for the title/subtitle/image/metadata components. Additionally, there is a "body" object in the pages which is a parsys and exposes other components if various types. I will update the question to give further information. – Dave Hughes Apr 07 '15 at 16:45
  • You are correct that the sling:include raises an invalid recursion selector error, in the case that an incorrect component is being included (component doesn't exist; or is of a type with no api.json.jsp because it is not intended for this query service). That invalid recursion selector error (400) is what we are trying to gracefully handle/suppress. – Dave Hughes Apr 07 '15 at 16:48
  • The question has been updated, please see "More info". – Dave Hughes Apr 07 '15 at 17:11