Get JSP output within Servlet in AEM

2k Views Asked by At

In CQ, we need to process jsp within servlet then combine the result with other results we get from server before writing back to browser.

The following code is almost what we need, except that it writes the result back to browser after processing jsp.

RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(request, response);

We tried using mock response as follows:

RequestData requestData = new RequestData(slingRequestProcessor, request, mockResponse);
SlingHttpServletRequest slingRequest = requestData.getSlingRequest();
SlingHttpServletResponse slingResponse = requestData.getSlingResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(slingRequest, slingResponse);

but we get issues.

2

There are 2 best solutions below

0
On BEST ANSWER

First off - based on your description it sounds like you want to use requestDispatcher.include and not requestDispatcher.forward.

Concerning the inclusion of the response content, the response which you pass into a requestDispatcher.include call could be an object of your own creation which would write its output to a string instead of returning it to the browser. Something along the lines of the following might be appropriate:

final ServletOutputStream outputStream = new ServletOutputStream() {
    public void write(int b) throws IOException {
        outputBuffer.append((char) b);
    }
};

SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
    public ServletOutputStream getOutputStream() {
        return outputStream;
    }

    public PrintWriter getWriter() throws IOException {
        return new PrintWriter(outputBuffer);
    }

    public SlingHttpServletResponse getSlingResponse() {
        return super.getSlingResponse();
    }
};

After the inclusion outputStream.toString() should provide the result of the resource request's execution.

0
On

Combining all feedback, this is what we come up with:

    //Map<String, Object> jstlValues, final Map<String, Object> propertyValues, String resourceType, SlingHttpServletRequest request, SlingHttpServletResponse response

    final StringWriter outputBuffer = new StringWriter();
    SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
        public PrintWriter getWriter() throws IOException {
            return new PrintWriter(outputBuffer);
        }

        public SlingHttpServletResponse getSlingResponse() {
            return super.getSlingResponse();
        }
    };

    ResourceMetadata resourceMetaData = new ResourceMetadata();
    resourceMetaData.setResolutionPath("/dummy");
    for (Map.Entry<String, Object> entry: jstlValues.entrySet()) {
        request.setAttribute(entry.getKey(), entry.getValue());
    }

    SyntheticResource resource = new SyntheticResource(request.getResourceResolver(), resourceMetaData, resourceType) {
        public <T> T adaptTo(Class<T> type) { 
             if (type == ValueMap.class) { 
                 ValueMap m = new ValueMapDecorator(propertyValues); 
                 return (T) m; 
             } 
             return super.adaptTo(type); 
         } 
    };
    RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
    dispatcher.include(request, responseWrapper);

    return outputBuffer.toString();