Search code examples
aemjcrsling

Sling Forward with SyntheticResource


I'm trying to build a Sling servlet that returns a modified value of a resource from the JCR. I dont want to change the original resource, so I create a SyntheticResource and make my manipulations. I then return it back using the RequestDispatcher.

The following code doesn't return the Modified content as expected and I don't see any errors in the log either. Can you tell me what I'm doing wrong here

@SlingServlet(methods = "GET", resourceTypes = "sling/components/test", selectors = "test")
public class TestServlet extends SlingSafeMethodsServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 4078524820231933974L;

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference
    ResourceResolverFactory resolverFactory;

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
        Map<String, Object> param = new HashMap<String, Object>();
        ResourceResolver resolver = null;
        response.setContentType("text/html");
        StringWriterResponse writerResponse = new StringWriterResponse(response);
        PrintWriter writer = response.getWriter();

        try {
            param.put(ResourceResolverFactory.SUBSERVICE, "testService");
            final String path = request.getRequestPathInfo().getResourcePath();
            resolver = resolverFactory.getServiceResourceResolver(param);
            final Resource resource = resolver.getResource(path);
            String resourceType = resource.getResourceType();

            Resource testResource = new SyntheticResource(resolver,
                    path, resourceType) {
                public <T> T adaptTo(Class<T> type) {
                    if (type == ValueMap.class) {
                        ModifiableValueMap map = resource
                                .adaptTo(ModifiableValueMap.class);
                        map.put("jcr:title", "Modified Title");
                        return (T)map;
                    }
                    return super.adaptTo(type);
                }
            };

            RequestDispatcherOptions requestDispatcherOptions = new RequestDispatcherOptions();
            requestDispatcherOptions.setReplaceSelectors("");
            final RequestDispatcher requestDispatcher = request.getRequestDispatcher(testResource, requestDispatcherOptions);

            requestDispatcher.forward(request, writerResponse);


            // log.debug( writerResponse.getString() );

            writer.println(writerResponse.getString());
            response.setStatus(HttpServletResponse.SC_OK );
        } catch (Exception e) {
            log.error("Exception: ", e);
        } finally {
            if( resolver != null) {
                resolver.close();
            }
            if( writer != null ){
                writer.close();
            }
            if (writerResponse != null) {
                writerResponse.clearWriter();
            }
        }


    }

}

Solution

  • Using a ResourceDecorator would be simpler, it can return a ResourceWrapper that implements the required changes. Just be careful to keep the decorator's decorate method efficient when it's called for a Resource that it doesn't want to decorate, as it will be called for all Resources.