Question

If we had component resource set up as such:

  • mycomponent
    • mycomponent.jsp
    • mycomponent.JSON.jsp

We can Assume it will work as such:

  • /path/to/mycomponent.html => see html
  • /path/to/mycomponent.json => see my json

Also in a servlet we might be able to do something like

Resource myResource = resourceResolver.getResource(request, "path/to/mycomponent");

I'm just curious how I might be able to get the .json representation in a servlet context as well.

I've done something that sort of solves this, but I was wondering if there was an alternate way, as this solution has huge limitations. Basically I load the Node at the path and do JSONDumps of the Node and it's children. This would allow me to get a larger set of JSON from the resource at the mycomponent.getPath(), but it doesn't allow me the ability to pull the custom JSON view i've created via mycomponent.JSON.jsp.

any thoughts/advice would be great, thank you.

Was it helpful?

Solution 2

The title of the question sounds like you want wanted to get the equivalent of a cURL/AJAX call to /path/to/mycomponent.-1.json but within a Servlet or other Java class.

You can use the org.apache.sling.commons.json.jcr.JsonItemWriter class to dump a JCR node into a JSONObject with infinite recursion. By passing in a Set into the constructor you can specify which properties to exclude from the final JSON. See http://www.nateyolles.com/blog/2015/12/converting-aem-sling-resources-to-json for more examples.

Resource resource = resolver.getResource("/content/my-app/my-page");

if (resource != null) {
    Node node = resource.adaptTo(Node.class);
    StringWriter stringWriter = new StringWriter();
    JsonItemWriter jsonWriter = new JsonItemWriter(null);

    try {
        jsonWriter.dump(node, stringWriter, -1);
        JSONObject jsonObject = new JSONObject(stringWriter.toString());
    } catch (RepositoryException | JSONException e) {
        LOGGER.error("Could not create JSON", e);
    }
}

You can also use the org.apache.sling.engine.SlingRequestProcessor class as Bertrand discussed above. See http://www.nateyolles.com/blog/2015/10/get-rendered-html-for-an-aem-resource-or-component for more examples.

@Reference
private RequestResponseFactory requestResponseFactory;

@Reference
private SlingRequestProcessor requestProcessor;

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
        throws ServletException, IOException {

    /* Setup request */
    HttpServletRequest req = requestResponseFactory.createRequest("GET",
            "/content/my-app/my-page.-1.json");

    /* Setup response */
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    HttpServletResponse resp = requestResponseFactory.createResponse(out);

    /* Process request through Sling */
    requestProcessor.processRequest(req, resp, request.getResourceResolver());
    String jsonString = out.toString();
}

OTHER TIPS

To capture the output of rendering a resource you can use the SlingRequestProcessor service, which makes a request internally without going through the network layers but still using all the same rendering mechanisms that are used to process HTTP requests.

If you just need to include such output in the rendering that you are computing you can use Request.getRequestDispatcher(somePathWithJsonExtension).include(request, response) which is what the Sling and CQ include JSP tags do.

Using resourceResolver.getResource(...) does not do any rendering, it just provides a raw Resource which is a data/content object.

Remember that you are using a JSP page to render out your JSON. If you are using a sling servlet to do this, there are several approaches that are feasible, but it's not the best approach to do so trying to write out responses directly yourself, especially since you have a JSP view to do that for you.

Have a look at this post:

servlet result display in jsp page

Specifically:

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    Object data = "Some data, can be a String or a Javabean";
    request.setAttribute("data", data);
    request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
}

If you just want to render out some JSON.

Otherwise, another less elegant option is to make a synchronous local HTTP request to the JSON.

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top