What is a Sling Filter?
Sling filters are basically OSGi services which are implementing javax.servlet.Filter interface. They are mostly used for authentication of request, post processing of markup or adding/modifying some request parameters etc. Sling supports filters by applying filter chains to the requests before actually dispatching to the servlet or script for processing. This sentence could be better described by the below image:
Two service properties are relevant to define a Sling filter :
- sling.filter.scope – Indicates the filter chain the filter should be part of. Required! Sling won’t pick up your filter if it isn’t set.
- service.ranking – Indicates the priority of the filter in the chain. The higher the number the earlier the filter will be invoked.
Sample Filter Implementation:
@SlingFilter( label = "Sample Filter", description = "Sample Description", metatype = true, generateComponent = true, // True if you want to leverage activate/deactivate generateService = true, order = 0, // The smaller the number, the earlier in the Filter chain (can go negative); scope = SlingFilterScope.REQUEST) // REQUEST, INCLUDE, FORWARD, ERROR, COMPONENT (REQUEST, INCLUDE, COMPONENT) @Properties({ @Property( label = "Vendor", name = "service.vendor", value = "SampleVendor", propertyPrivate = true ) }) public class SampleSlingFilter implements Filter { private static final Logger log = LoggerFactory.getLogger(SampleSlingFilter.class.getName()); @Override public void init(FilterConfig filterConfig) throws ServletException { // Usually, do nothing } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof SlingHttpServletRequest) || !(response instanceof SlingHttpServletResponse)) { // Not a SlingHttpServletRequest/Response, so ignore. chain.doFilter(request, response); // This line would let you proceed to the rest of the filters. return; } final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response; final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request; final Resource resource = slingRequest.getResource(); if (resource.getPath().startsWith("/content/pqr")) { // Is the SlingFilterScope is REQUEST, redirects can be issued. //Write your custom code here. slingResponse.sendRedirect("/abc/xyz.html"); return; } // to proceed with the rest of the Filter chain chain.doFilter(request, response); } @Override public void destroy() { // Usually, do Nothing } @Activate protected void activate(final ComponentContext componentContext) throws Exception { final Map<String, String> properties = (Map<String, String>) componentContext.getProperties(); } @Deactivate protected void deactivate(ComponentContext ctx) { } }
You may see the current filters implemented in your local instance using the link:
http://localhost:4502/system/console/status-slingfilter
what changes we have to made to run your sling filter at the end.?
LikeLike
I believe you would just be needing some imports. Rest it should be working.
LikeLike
Hey I have doubt it might not be relevant to this topic but guide please.
Is it possible to add our own tag in dam filter ?
To be more specific in DAM search we have filter below that tags with business,entertainment, etc.
My qus is , is it possible to add our own tag to that list ? if yea please guide me
TIA
LikeLike
Hi, I am not sure what do you mean by new dam filter. Please check the link : https://docs.adobe.com/docs/en/cq/5-6-1/wcm/tag_admin.html if you want to create a new tag or namespace.
LikeLike
Thanks for the reply.
I created the namespace, tag and everything.
The task given to me was In DAM search page
We have a option to restrict our search by selecting business or entertainment right ?
I am asking in there is was supposed to add my namespace .
Googled but unable to find any where.
LikeLike
Hi, You need to look into overriding the DAM Search Panel , either by overriding extra nodes or creating a Custom Predicate . Please check the links at :
https://docs.adobe.com/docs/en/cq/5-6-1/dam/extending-cq-dam-search.html
https://docs.adobe.com/docs/en/aem/6-1/develop/extending/assets/searchx.html
Look for path :
For Siteadmin Search : /libs/wcm/core/content/search/searchpanel/facets
For DamAdmin Search: /libs/dam/content/search/searchpanel/facets/tagoptions
You need to override these paths , create Tags as per your project and then change property
optionsPaths
LikeLike
Thanks man. Worked like a charm. One more small help if you can.
I am unable to find any links in your page related to downloading image from DAM. Cause when i click on download it just opens in new page.
Sorry for the trouble and thank you
LikeLike
Hi Hashim – Thanks for a wonderful article out here. really insightful.
does this solution is assuming that users are accessing publisher directly? mostly production systems are on dispatcher or behind akamai.
LikeLike
Hi, You’re welcome.
Sling filters would come in picture only when the request would hit Publishers for the first time. After the first time , dispatcher and Akamai can cache the response itself, if that is needed. (You can always skip the caching as per need. )
Filter chain is active only when AEM instances are hit by user request. Check the complete flow here: https://sling.apache.org/documentation/the-sling-engine/dispatching-requests.html
LikeLike
Hi Hashim,
I followed your example to implement the filter, my requirement is on a web page link structure will be “/en-us/collaterals/a.pdf”. where as in AEM it resides in DAM structure it will reside in below location “/content/dam/XXX/collaterals/en/a.pdf”. below is my filter code. With this code I am seeing the blank PDF page instead of actual content. As per my requirement I should not change the end use URL, sue to this I am not able to use sendredirect. I tried with dispatch.include and dispatch.forward. Both has the same issue. Please help me what I am doing wrong.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
if (!(request instanceof SlingHttpServletRequest) || !(response instanceof SlingHttpServletResponse)) {
chain.doFilter(request, response); // This line would let you proceed to the rest of the filters.
return;
}
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
final Resource resource = slingRequest.getResource();
String path = resource.getPath();
String uri = slingRequest.getRequestURI();
String localeRegExPattern=”^/[a-z]{2}-[a-z]{2,5}/collaterals/+”;
Pattern pattern = Pattern.compile(localeRegExPattern) ;
Matcher matcher = pattern.matcher(uri);
boolean matchFound = matcher.find();
System.out.println(“::::::::::::::matchFound:::::::::::::::. “+matchFound);
if (matchFound) {
uri = pattern.matcher(uri).replaceAll(StringUtils.EMPTY);
System.out.println(“::::::::::::::New URL Pattern Found. “);
String tempURI = “/content/dam/XXX/collaterals/en/”+uri;
System.out.println(“::::::::::::::tempURI:::::::::::::::::::::. “+tempURI);
RequestDispatcher dispatch = request.getRequestDispatcher(tempURI);
dispatch.include(request, response);
//slingResponse.sendRedirect(tempURI);
return;
}
else {
chain.doFilter(request, response);
}
Thanks in Advance.
Kumar
LikeLike
Hi,
First of all Instead of pattern matching you should use sling.filter.pattern to restrict URLs. https://sling.apache.org/documentation/the-sling-engine/filters.html.
What are you trying to do here ? What is the use case ?
LikeLike
Hi Hashim,
Could you please let me know how can I use sling.filter.pattern in the @SlingFilter Annotation ? I have used it like below :
@SlingFilter(
label = “Filter implementation”,
metatype = true,
generateComponent = true,
generateService = true,
order = 1,
scope = SlingFilterScope.REQUEST
)
@Properties({
@Property(name=”service.description”, value=”A Filter”),
@Property(name=”sling.filter.pattern”, value=”/some/path”)
})
Could please help me understand if it’s correct to use sling.filter.pattern this way in AEM 6.3 to restrict the filter to run for specific url pattern or it can only be done by including custom logic inside the filter class ?
The context behind using this is to restrict the filter to run for urls having only “xyz” in it. Eg Url: content/xyz/homepage.html.
Also please tell me what kind of regular expression I need to use to restrict the patter according to my requirement.
I couldn’t find a single relevant example or documention according to my requirement.
LikeLiked by 1 person