Sling Component Filters in CQ5
Sling Component Filters in CQ5
1
Agenda
• The Sling Request Invocation Chain
• Implementing own Sling Filters
• Use Cases and Samples
2
!!!WARNING!!!
Sling Filters are a very generic and mighty extensionpoint. When
utilizing them you should always have in mind that AEM/CQ Core
functionality relies on the data provided by Sling, manipulation
of this data therefore may break CQ.
3
The Sling Request Invocation Chain
How the Sling Engine processes HTTP Requests
4
Sling Request Invocation Chain
SlingMainServlet
Registered as Services
SlingRequestProcessor (preferably via SCR Annotation)
dispatchRequest() processRequest()
Filter A
FilterChain
Scope: REQUEST
FilterManager Filter B
FilterChain
Scope: COMPONENT
Filter C
Component Servlet
INCLUDE/FORWARD
5
Implementing Sling Filters
How to use Filters as Extensionpoint
6
Registration of Filters
• Standard Servlet Filter (javax.servlet.Filter)
– Need to be registered as Service („manually“ or SlingFilter SCR Annotation)
• Order and FilterScopes can be defined
• Filterscopes
– REQUEST
– COMPONENT
– ERROR
– INCLUDE *
– FORWARD *
* FilterChain executes COMPONENT scope for these scopes as well.
7
SCR Annotation
@SlingFilter(scope = SlingFilterScope.COMPONENT, order = -10000, metatype =
false)
public class MyComponentFilter implements javax.servlet.Filter {
@Override
public void doFilter(ServletRequest pRequest, ServletResponse pResponse,
FilterChain pChain) throws IOException, ServletException {
// Implement Filter
8
Filter Order
• Existing Filters might use the deprecated „filter.order“ instead
„service.ranking“
• NOTE: SLING-2920 was identified while verifying this behavior – look up the
mailing list for further information how to use it for now
9
Check Filterconditions at first place
public void doFilter(ServletRequest pRequest, ServletResponse pResponse,
FilterChain pChain) throws IOException, ServletException {
if (!(pRequest instanceof SlingHttpServletRequest)) {
throw new ServletException("Request is not a Sling HTTP request.");
}
if (isFilterEnabled(slingRequest)) {
// Implement Filter-Logic
} else {
// continue with filter chaining
pChain.doFilter(pRequest, pResponse);
}
}
10
Accessing and Using Data in Filter
public void doFilter(ServletRequest pRequest, ServletResponse pResponse,
FilterChain pChain) throws IOException, ServletException {
if (!(pRequest instanceof SlingHttpServletRequest)) {
throw new ServletException("Request is not a Sling HTTP request.");
}
if (isFilterEnabled(slingRequest)) {
Resource resource = slingRequest.getResource(); // already resolved
if (null != resource) {
PrintWriter writer = pResponse.getWriter();
writer.write("<component resourceType=\"" + resource.getResourceType()
"\">");
pChain.doFilter(pRequest, pResponse);
writer.write("</component>");
return;
}
}
pChain.doFilter(pRequest, pResponse);
}
11
Useful Wrapper Objects in Filters
• SlingHttpServletRequestWrapper
– Implement to override parts of the request
• E.g. Inject impersonated ResourceResolver*
• SlingHttpServletResponseWrapper
– Implement to inject additional logic to response
• E.g. inject own writer to buffer the response to perform some postprocessing
* Security-Note: Make sure you don’t create security holes this way – the request
should always respect the permissions of the current user!
12
Dispatch to other Resource
RequestDispatcher dispatcher =
slingRequest.getRequestDispatcher(otherResource);
dispatcher.forward(request, response);
Note: You should be aware that a Dispatcher Forward or Include will retrigger
the FilterChain. Place such filters early in the Filterchain to prevent other
Filters to be executed twice.
13
Usecases & Samples
14
Usecases
• Logging
• Measuring
• Decoration
• Pre-Processing
• Post-Processing
• Manipulating Inclusions
15
Logging
• Allows to hook in Requestcentric logging at Sling Level
• It is possible to log even requests/includes of components which are not
part of the own application (like foundation components)
• Sample
– org.apache.sling.engine.impl.debug.RequestProgressTrackerLogFilter
16
Measuring
• Since the Filterchain gets consulted at each call of a component they
provide a natural location to measure the actual usage of the system
17
Decoration
• Adding generic but usecasespecific decoration to components
• Sample
– WCMDebugFilter ( for Requestparameter debug=layout)
• Further Usecase
– For specific selector: Metadata for third party systems like
• Search Parsers
• Integrating Systems (e.g. Portals)
18
Preprocessing
• Injecting data that needs to be available within the components
• Sample:
– WCMComponentFilter – generic logic that links CQ Authoring logic with Sling
Components
– I18nFilter – Injecting I18n Resource Bundles
• Further Usecases
– Build Java Bean and place in Request to be used via jsp:useBean and EL within
JSPs (Sepearation of businesslogic)*
19
Postprocessing
• Injecting custom writer to postprocess output
• Sample:
– RewriterFilter
• Further Usecases:
– Integration of thirt party markup (e.g. via Velocity or Freemarker)
– Injection of a generic Placeholderlogic (e.g. Personalization)
20
Manipulating Inclusions
• Redirecting , Skipping or manipulating further processing
• Samples:
– Mobile RedirectFilter (trigger Redirect with matching selector for device)
– TimeWarp Filter ( replacing ResourceData & corresponding Objects with Objects at
given Timestamp)
• Further Usecases
– Controlled Impersonation in Author Mode for Permissionpreview
(Publishpermissions)
– Component Level Caching (Record response to cache and answer subsequent
requests from cache)*
* Not yet verified, but might be a solution for partial caching where dispatcher caches
cannot be used
21
Some last words…
• The Apache Sling Stack is the core of CQ5 / AEM
• Apache Sling is an open source project that relies on an active community
;)
22
Contact
Karim Khan
Tel. +49 (69) 8700328-0
E-Mail kkhan@pro-vision.de
Berlin Frankfurt
pro!vision GmbH pro!vision GmbH
Wilmersdorfer Str. 50-51 Löwengasse 27 A
10627 Berlin 60385 Frankfurt am Main
Germany Germany
23