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 theComponentRequestDispatcher
interface which may be called after acquiring the object but before calling theinclude
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.