RequestResponseFactory and FakeRequest | Community
Skip to main content
Linda_Jufferma1
March 15, 2018

RequestResponseFactory and FakeRequest

  • March 15, 2018
  • 2 replies
  • 6573 views

Hi,

We use the RequestResponseFactory to retrieve content from AEM inside an OSGi bundle:

The service is obtained through:

@Reference

private RequestResponseFactory requestResponseFactory;

And used like this:

final HttpServletRequest servletRequest = requestResponseFactory.createRequest("GET", path);

WCMMode.DISABLED.toRequest(servletRequest);

final ByteArrayOutputStream responseOutputStream = new ByteArrayOutputStream();

final HttpServletResponse servletResponse = requestResponseFactory.createResponse(responseOutputStream);

servletResponse.getWriter().flush();

byte[] content = responseOutputStream.toByteArray();

Most methods of the FakeRequest class return null; e.g. getHeader, getServerName.

FakeRequest seems to cause errors that normal requests don't, e.g.:

15.03.2018 11:22:30.322 *ERROR* [pool-5-thread-2] com.day.cq.wcm.tags.IncludeTag Error while executing script view.jsp

org.apache.sling.api.scripting.ScriptEvaluationException:

  at org.apache.sling.scripting.core.impl.DefaultSlingScript.call(DefaultSlingScript.java:388)

  at org.apache.sling.scripting.core.impl.DefaultSlingScript.eval(DefaultSlingScript.java:171)

  at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:463)

  at com.day.cq.wcm.tags.IncludeTag.includeScript(IncludeTag.java:176)

  ...

Caused by: java.lang.UnsupportedOperationException: null

  at com.day.cq.contentsync.impl.handler.util.FakeRequest$FakeHttpSession.getAttribute(FakeRequest.java:64)

  at org.apache.sling.scripting.jsp.jasper.runtime.PageContextImpl.doFindAttribute(PageContextImpl.java:470)

  at org.apache.sling.scripting.jsp.jasper.runtime.PageContextImpl.findAttribute(PageContextImpl.java:455)

  at org.apache.jsp.apps.lgi_002dforms.components.forms.honeypot.honeypot_jsp._jspService(honeypot_jsp.java:122)

where honeypot_jsp.java:122 is:

currentNode = (javax.jcr.Node) _jspx_page_context.findAttribute("currentNode");

which is compiled from this line in the JSP:

<cq:defineObjects />

We use the RequestResponseFactory with the SlingRequestProcessor for ContentSync handler and a customer service that uploads pages to an FTP server. Should we use RequestResponseFactory for these or is there a better method? How can we work around the issues described above?

Linda

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

2 replies

smacdonald2008
Level 10
March 15, 2018

Can you point to the URL where you found this information. We can see if we can reproduce your issue.

Typically to get node information from the AEM JCR - you use code like this with a system user.

Map<String, Object> param = new HashMap<String, Object>();

param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");

ResourceResolver resolver = null;


try {

          

    //Invoke the adaptTo method to create a Session used to create a QueryManager

  resolver = resolverFactory.getServiceResourceResolver(param);

    session = resolver.adaptTo(Session.class);

Linda_Jufferma1
March 16, 2018

There's Retrieve the HTML contents of a cq:Page  and RequestResponseFactory ("The Adobe AEM Quickstart and Web Application.") ...

I'm not trying to get node information, I'm trying to retrieve content (HTML and client libraries).

smacdonald2008
Level 10
March 16, 2018

Interesting - we do not have any HELPX examples on this use case. Let me try and find a better example than the one referencd in the URL. However - this provided a lot more detail on what you are trying to do.

joerghoh
Adobe Employee
Adobe Employee
May 14, 2018

I ran about this issue some time ago: Sling - Users - Fake request/response classes

As follow up [SLING-5428] Move MockSlingHttpServletRequest+Response to org.apache.sling.servlet-helpers - ASF JIRA  has been created and it should be available in a separate bundle you can deploy to your instance (not sure if it's provided ootb in AEM in the meanwhile).

Jörg

sherrylynnh1858
May 17, 2018

Thanks Jorg and Linda for you replies.

Linda, I've tried the URL approach but find I get a 401

Jorg,

So I've tried to use Apache Sling :: Sling Servlet Helpers ​but don't appear to be able to get at the content... I can't be using the servlet helpers correctly?

I added the dependency to my pom as follows:

<dependency>
  <groupId>org.apache.sling</groupId>
  <artifactId>org.apache.sling.servlet-helpers</artifactId>
  <version>1.1.2</version>
</dependency>

and replaced response and request with mock versions as you'll see below (I've commented them out). I had to move things around because MockSlingHttpServletRequest requires a ResourceResolver.

@SlingServlet(

  paths={"/services/foo/bar"},

  methods = "GET"

)

@Slf4j

public class MyAnalysisServlet extends SlingSafeMethodsServlet {

  private static final long serialVersionUID = 1L;

  private static final String HEADER_REFERRER = "referer";

  private static final String EDITOR_PATH_PREFIX = "/editor.html";

  @Reference

  private transient RequestResponseFactory requestResponseFactory;

  @Reference

  private transient ResourceResolverFactory resourceResolverFactory;

  @Reference

  private transient SlingRequestProcessor requestProcessor;

  @Override

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

    final String referrer = request.getHeader(HEADER_REFERRER);

    handleRequest(request, response, referrer);

  }

private void handleRequest(SlingHttpServletRequest request, SlingHttpServletResponse response, final String referrer) throws ServletException, IOException {

  final String content = loadContent(referrer);

  try {

    sendResultResponse(request, response, referrer, content);

  } catch (ExecutionException e) {

    sendErrorOrThrow(response, e);

  }

}

private String loadContent(String referrer) throws ServletException, IOException {

  String contentPath = getContentPath(referrer);

  final HttpServletRequest request = requestResponseFactory.createRequest("GET", contentPath);

  WCMMode.PREVIEW.toRequest(request);

  final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

  final HttpServletResponse response = requestResponseFactory.createResponse(outputStream);

// final MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();

  ResourceResolver resourceResolver = null;

  try {

    // ** the bundle is whitelisted as getAdministrativeResourceResolver(null) is deprecated **

    resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);

//  MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);

//  WCMMode.PREVIEW.toRequest(request);

    

     requestProcessor.processRequest(request, response, resourceResolver);

  } catch (LoginException e) {

     throw new ServletException("Error obtaining administrative resource resolver", e);

  } finally {

    if (resourceResolver != null) {

      resourceResolver.close();

    }

  }

  final String content = outputStream.toString(Charsets.UTF_8.name());

  // strip HTML comments

  return content.replaceAll("(?s)<!--.*?-->", "<!-- [Stripped comment placeholder] -->");

}

  private String getContentPath(String referrer) throws MalformedURLException {

    return //does stuff to the path;

  }

  private void sendResultResponse(SlingHttpServletRequest request, final SlingHttpServletResponse response, final String url, final String content) {

    // does stuff

  }

  private void sendErrorOrThrow(SlingHttpServletResponse response, ExecutionException e) throws IOException, ServletException {

    // does stuff

  }

}

Any ideas/pointers?

Many thanks for you time.