DS Annotations – Sling Filter


Sling supports filter processing by applying filter chains to the requests before actually dispatching to the servlet or script for processing. They can be used to call a servlet, to redirect to another page, to authenticate request, preprocessing, post-processing of mark up, logging, measuring, decoration or adding/removing request parameters.

Filters to be used in such filter processing are plain OSGi services of type javax.servlet.filter. Following properties are available to configure a filter.

PropertyTypeDefault ValueValid ValuesDescription
sling.filter.scopeString

 

String[]

Vector

requestREQUEST

 

INCLUDE

FORWARD

ERROR

COMPONENT

Indication of which chain the filter should be added to. This property is required. If it is missing from the service, the service is ignored because it is assumed another consumer will be interested in using the service. Any unknown values of this property are also ignored causing the service to be completely ignored if none of the values provided by the property are valid.
service.rankingInteger0Any Integer valueIndication of where to place the filter in the filter chain. The higher the number the earlier in the filter chain. This value may span the whole range of integer values. Two filters with equal service.ranking property value (explicitly set or default value of zero) will be ordered according to their service.id service property
sling.filter.patternString(-)Any String valueRestrict the filter to paths that match the supplied regular expression. Requires Sling Engine 2.4.0.
sling.filter.suffix.patternString(-)Any String valueRestrict the filter to requests with suffix that match the supplied regular expression. Requires Sling Engine 2.6.14.
sling.filter.selectorsString[](-)Any String valueRestrict the filter to requests whose selectors match one or more of the provided ones. Requires Sling Engine 2.6.14.
sling.filter.methodsString[](-)Any String valueRestrict the filter to requests whose methods match one or more of the provided ones. Requires Sling Engine 2.6.14.
sling.filter.resourceTypesString[](-)Any String valueRestrict the filter to requests whose resource type match one of the provided ones. Requires Sling Engine 2.6.14.
sling.filter.extensionsString[](-)Any String valueRestrict the filter to requests whose extension matches one of the provided ones. Requires Sling Engine 2.6.14.

Examples:

  • REQUEST Scope: Following example logs message when a techrevel page is accessed in AEM.
package blog.techrevel.service.impl;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import static org.apache.sling.engine.EngineConstants.*;
import org.apache.sling.api.resource.Resource;
import org.osgi.service.component.annotations.Component;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
@Component(service = Filter.class, name = "Custom Logging Filter", property = {
SLING_FILTER_SCOPE + "=" + FILTER_SCOPE_REQUEST, Constants.SERVICE_RANKING + ":Integer=1",
SLING_FILTER_PATTERN + "=/content/techrevelblog/.*" })
public class RequestLoggingFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class.getName());
// Called by the web container to indicate to a filter that it is being placed
// into service.
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
// Called by the web container to indicate to a filter that it is being taken
// out of service.
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof SlingHttpServletRequest && response instanceof SlingHttpServletResponse) {
// Do work before sending the request down the Filter AND Sling processing chain
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
final Resource resource = slingRequest.getResource();
if (resource.getResourceType().equals("cq:Page")) {
PageManager pageManager = resource.getResourceResolver().adaptTo(PageManager.class);
Page page = pageManager.getPage(resource.getPath());
String templatePath = page.getContentResource().getResourceType();
if (templatePath.equals("techrevelblog/components/structure/page")) {
log.info("Pages from techrevel accessed !!!!");
}
}
chain.doFilter(request, response);
// The Request/Response have now been fully processed by Sling/AEM
} else {
// Else process the chain as usual.
chain.doFilter(request, response);
return;
}
}
}

Filter Processing

Filter processing is part of the Sling request processing, which may be sketched as follows:

  • Request Level (Level 1):
    • Authentication
    • Resource Resolution
    • Servlet/Script Resolution
    • Request Level Filter Processing

The first step of request processing is the Request Level processing which is concerned with resolving the resource, finding the appropriate servlet and calling into the request level filter chain. The next step is the Component Level processing, calling into the component level filters before finally calling the servlet or script:

  • Component Level (Level 2):
    • Component Level Filter Processing
    • Call Servlet or Script

When a servlet or script is including or forwarding to another resource for processing through the RequestDispatcher the following Dispatch processing takes place:

  • Dispatch (Level 3):
    • Resolve the resource to dispatch to if not already defined when getting the RequestDispatcher
    • Servlet/Script resolution
    • Call include or forward filters depending on the kind of dispatch
    • Call Servlet or Script

As a consequence, request level filters will be called at most once during request processing (they may not be called at all if a filter earlier in the filter chain decides to terminate the request) while the component level, include, and forward filters may be called multiple times while processing a request.

Error Filters are called upon HttpServletResponse.sendError or any uncaught Throwable before resolving the error handler Servlet or script.

Disabling Filters

A filter is ignored if you set an invalid sling.filter.scope. To disable a specific filter, you can deploy an OSGi config setting an invalid sling.filter.scope, for instance disabled.

One thought on “DS Annotations – Sling Filter

Leave a comment