|
Page Edited :
SLINGxSITE :
Servlet Resolution
Servlet Resolution has been edited by Mike Mueller (Apr 15, 2009). Change summary: Mention the SLING-923 examples and tests Servlet Resolution
Servlets are ResourcesAs explained on the Resources page, the Resource is the central data abstraction of Sling. In this contexts, Servlets are of course also povided as Resources. As such Servlets may be enumerated by iterating the Resource tree and Servlets may be retrieved through the ResourceResolver. To show a Servlet inside the Resource tree, the sling/servlet-resolver project provides a ServletResourceProvider implementing the ResourceProvider interface. For each Servlet registered as an OSGi service with one or more defined service reference properties a ServletResourceProvider instance is registered. The following service reference properties are defined for Servlets defined as OSGi services of type javax.servlet.Servlet:
For a Servlet registered as an OSGi service to be used by the Sling Servlet Resolver, the following restrictions apply:
Each path to be used for registration – either from the sling.servlet.paths property or constructed from the other sling.servlet.* properties – must be absolute. Any relative path is made absolute by prefixing it with a root path. This prefix may be set with the sling.servlet.prefix service registration property. If this property is not set, the first entry in the ResourceResolver search path for the ResourceResolver.getResource(String) method is used as the prefix. If this entry cannot be derived, a simpe slash – / – is used as the prefix. Example: Registration by Pathsling.servlet.paths = [ "/libs/sling/sample/html", "/libs/sling/sample/txt" ] sling.servlet.resourceTypes = [ "sling/unused" ] sling.servlet.selectors = [ "img" ] sling.servlet.extensions = [ "html", "txt", "json" ]
The registration properties sling.servlet.resourceTypes, sling.servlet.selectors and sling.servlet.extensions are ignored because the sling.servlet.paths property is set. Example: Registration by Resource Type etc.sling.servlet.resourceTypes = [ "sling/unused" ] sling.servlet.selectors = [ "img", "tab" ] sling.servlet.extensions = [ "html", "txt", "json" ] A Servlet service registered with these properties is registered under the following paths:
As explained the script is registered for each permutation of the resource types, selectors and extension. See above For an explanation of how prefix is defined. Scripts are ServletsThe Sling API defines a SlingScript interface which is used to represent (executable) scripts inside of Sling. This interface is implemented in the scripting/resolver bundle in the DefaultSlingScript class which also implements the javax.servlet.Servlet. To further simplify the access to scripts from the Resource tree, the scripting/resolver bundle registers an AdapterFactory to adapt Resources to Scripts and Servlets. In fact the adapter factory returns instances of the DefaultSlingScript class for both Scripts and Servlets. This functionality is used by the ServletResolver.resolveServlet implementation in the sling/servlet-resolver bundle: This implementation just looks up any Resource in the resource tree according its lookup algorithm (see below). The first matching Resource adapting to a javax.servlet.Servlet is used for processing the resource. So from the perspective of the Servlet resolver, scripts and servlets are handled exactly the same. Resolution ProcessThe Servlet Resolution Process four elements of a SlingHttpServletRequest:
The resource type is used as a (relative) parent path to the Servlet while the request extension or request method is used as the Servlet (base) name. The Servlet is retrieved from the Resource tree by calling the ResourceResolver.getResource(String) method which handles absolute and relative paths correctly by searching realtive paths in the configured search path. The pseudo-code for Servlet resolution is as follows: Servlet resolveServlet(SlingHttpServletRequest request) {
String resourceType = request.getResource().getResourceType();
resourceType = resourceType.replaceAll("\\:", "/");
String baseName;
if (("GET".equals(request.getMethod()) || "HEAD".equals(request.getMethod())
&& request.getRequestPathInfo().getExtension() != null) {
baseName = request.getRequestPathInfo().getExtension();
} else {
baseName = request.getMethod();
}
if (request.getRequestPath().getSelectorString() != null) {
String selectors = request.getRequestPath().getSelectorString();
selectors = selectors.replace('.', '/');
while (selectors != null) {
String path = resourceType + "/" + selectors + "/" + baseName;
Servlet servlet = findServletFor(path);
if (servlet != null) {
return servlet;
}
int lastSlash = selectors.lastIndexOf('/');
if (lastSlash > 0) {
selectors = selectors.substring(0, lastSlash);
} else {
selectors = null;
}
}
}
String path = resourceType + "/" + baseName;
return findScriptFor(path);
}
Servlet findScriptFor(path) {
// Find a Servlet or Script with the given path in the search path
// where the Script is allowed to have Script language specific
// extension, such as .js, .jsp, etc.
}
Default Servlet(s)As explained in the Resolution Process section above, a default Servlet is selected if no servlet for the current resource type can be found. To make the provisioning of a default Servlet as versatile as provisioning per resource type Servlets (or scripts), the default Servlet is selected with just a special resource type sling/servlet/default. The actual Servlet or Script called as the default Servlet is resolved exactly the same way as for any resource type. That is, also for the default Servlet selection, the request selectors and extension or method are considered. Also, the Servlet may be a Servlet registered as an OSGi service and provided through a Servlet Resource provider or it may be a Script stored in the repository or provided by the bundle. Finally, if not even a registered default Servlet may be resolved for the request, because none has been registered, the sling/servlet-resolve bundle provides a fall back DefaultServlet with the following functionality:
Error Handler Servlet(s)The sling/servlet-resolver project also provides an implementation of the Sling Core ErrorHandler interface, which applies the same Servlet resolution process as used for normal request processing. Error handler Servlets and Scripts are looked up with the predefined resource sling/servlet/errorhandler and an error specific name:
Integration testsA set of simple example servlets is available in the launchpad/test-services module Integration tests in the launchpad/testing module Contributions to these tests and examples are welcome, of course! |
Unsubscribe or edit your notifications preferences
