Apache Jackrabbit : ApacheSling SlingGuideRequestDispatching

Dispatching requests in Sling Applications

Sling is built upon the Component API which has componentizing the page rendering as one of its corner stones. Therefore including the result of handling, rendering that is, a Content object is a central issue in Sling. To this avail the following methods are provided by the Component API:

ComponentRequest.getRequestDispatcher(Content)

Allows the inclusion of rendering of the given Content object.

ComponentRequest.getRequestDispatcher(String)

Allows the inclusion of rendering a Content object or, if no such object exists, delegation to the whatever container Sling is running in. In the case of Sling this is of course the delegation to the Servlet Container.

ComponentContext.getRequestDispatcher(Content)

Allows the inclusion of rendering of the given Content object.

ComponentContext.getRequestDispatcher(String)

Allows the inclusion of rendering a Content object or, if no such object exists,

delegation to the whatever container Sling is running in. In the case of Sling this is of course the delegation to the Servlet Container.

Note, that the methods in the ComponentRequest and in the ComponentContext are exactly the same. The reason to have them in both places is actually alignement with the Servlet API specification which has also respective methods in both places.

Examples

Example 1 - Including content with an object

Content someContent = request.getContent("/abs/path/to/content");
ComponentRequestDispatcher crd = request.getRequestDispatcher(someContent);
crd.include(request, response);

This example first acquires the Content object from the request, gets the request dispatcher to render the content and finally includes this rendering.

Example 2 - Including content with a path

ComponentRequestDispatcher crd = request.getRequestDispatcher("/abs/path/to/content");
crd.include(request, response);

This second example is equivalent to the first except, that acquiring the Content object is delegated to the request dispatcher and delayed until the output is actually requested for inclusion. Of course, if there is no Content object at the given path, this example will fall back to getting a dispatcher from the servlet container and dispatch to the resource /abs/path/to/content through the servlet container.

Dispatching also works with a relative path, like this:

ComponentRequestDispatcher crd = request.getRequestDispatcher("jcr:content");
crd.include(request, response);

If no child content of the Content of the request is available, the request dispatcher will try to include a servlet container resource whose path is relative to the current request.

JSP Request Dispatching

For scripted components handled by JSP, request dispatching works using either the Servlet API (e.g. ServletRequest.getRequestDispatcher(String)) or by using the <jsp:include> tag. In the JSP integration provided by the Sling Core Scripting, the request dispatcher returned will actually use a ComponentRequestDispatcher retrieved from the current request using the path given.

As a result, JSPs may include servlet container resources for rendering but also benefit from content mapping. For example, by using

<jsp:include path="jcr:content" />

the output of rendering the jcr:content child content of the request's content may easily be included in JSPs.

Note: The preferred way is of course to use the <sling:include> tag.

Issues with Request Dispatching

The following is a short list of current limitations of request dispatching:

  • The current implementation just takes the path used to acquire the request dispatcher as is and tries to load the Content object. There is no support to resolve in a way as the URL Mapper does.
  • Passing additional request parameters, providing a different request extension or a custom selector list is not currently supported by the ComponentRequestDispatcher. It is foreseen to provide such functionality with additional API on the ComponentRequestDispatcher interface which may be called after acquiring the object but before calling the include method.
  • Request forwarding as per javax.servlet.RequestDispatcher.forward is not currently supported. As a workaround, a simple redirection (with all its consequences) may be used.