Enable or Disable Dispatcher Cache
As we all know, there are two main advantages of using dispatcher, first is to balance the load in between multiple publish AEM instance and second to Cache content.
There is a /cache section in dispatcher.any file where we can define caching rule to cache content. Within /cache section we have /rules which helps us to write glob pattern as deny or allow to cache content.
Below rule allow as * will help us to cache every URL and content.
/cache
{
/docroot "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
/rules
{
/0000
{
/glob "*"
/type "allow"
}
}
}
The /rules property controls which documents are cached according to the document path. Regardless of the /rules property, Dispatcher never caches a document in the following circumstances:
- If the HTTP method is not GET.
- If the request URI contains a question mark (“?”).
- The file extension is missing.
- The authentication header is set (this can be configured)
Let’s create a below path based servlet and try to cache things:
package com.javadoubts.core.servlets;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.json.JSONException;
import org.json.JSONObject;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Servlet;
import java.io.IOException;
import java.util.Random;
@Component(
service=Servlet.class,
property={
Constants.SERVICE_DESCRIPTION + "=Test Cache Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.paths=" + "/bin/practice/path",
Constants.EXTENSION_DIRECTIVE + "=json"
}
)
public class TestCacheServletByPath extends SlingAllMethodsServlet {
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void doGet(final SlingHttpServletRequest req,
final SlingHttpServletResponse resp) throws IOException {
logger.error("Servlet called");
resp.setStatus(SlingHttpServletResponse.SC_OK);
resp.setContentType("application/json;charset=UTF-8");
JSONObject json = new JSONObject();
Random ran = new Random();
int num = ran.nextInt(100);
try {
json.put("number", num);
} catch (JSONException e) {
logger.error("Exception >>>>> ", e);
}
resp.getWriter().print(json);
}
}
This is a GET servlet having no parameter defined will allow us to cache its servlet response as we have already defined allow as * in /rules section.
Hitting http://localhost/bin/practice/path.json URL will always give us the same response as response is cache.
Below is the sample /ignoreUrlParams section which help us to cache content depending on the query parameter e.g. http://localhost/bin/practice/path.json?q=1
Every time hitting above URL having parameter a q will always give same output.
/cache
{
# The ignoreUrlParams section contains query string parameter names that
# should be ignored when determining whether some request's output can be
# cached or delivered from cache.
#
# In this example configuration, the "q" parameter will be ignored.
/ignoreUrlParams
{
# /0001 { /glob "*" /type "deny" }
/0002 { /glob "q" /type "allow" }
# }
}
Same UR http://localhost/bin/practice/path.json?q=1 having different responses:
How To Test
URL having any query parameter other than ‘q’ will allow us to load latest Not Cached content:
http://practice.abc/bin/practice/path.json?test=22
Disable Caching
There are two different ways to avoid caching of specific URL:
Using Dispatcher
- set deny as * to within /rules section to disable 100% caching:
/cache
{
/rules
{
/0000 { /glob "*" /type "deny" }
}
}
Disable caching for specific URL
Set deny rule as part of /rules section to avoid caching. /bin/practice/path.json URL will not get cache any more.
/cache
{
/rules
{
/0000 { /glob "*" /type "allow" }
/0001 { /glob "/bin/practice/path.json" /type "deny" }
}
}
Using response header
In Java Class
Declaring below line as part of TestCacheServletByPath.java servlet doGet() method will not cache response and always return latest response.
resp.setHeader("Dispatcher", "no-cache");
In JSP
With the Dispatcher release 4.0.0 (and higher) a new header named “Dispatcher: no-cache” is introduced. This header informs the dispatcher not to cache the response. This header will then be removed by the dispatcher before forwarding the response to the client.
In order to disable caching in the dispatcher, add the header “Dispatcher: no-cache”, i.e. in your JSP:
<%
response.setHeader("Dispatcher", "no-cache");
%>
Sling Model
Below is the code snippet to disable cache as part of sling model.
@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ButtonModel {
@Inject
private SlingHttpServletResponse response;
@PostConstruct
protected void init() {
response.setHeader("Dispatcher", "no-cache");
}
}
Using ACS Commons OSGI Configuration TTL based
It will require to install AEM ACS Commons package to install. ACS AEM Commons allow us to perform TTL based timeout caching. This allow us to invalidate cache at specific time or interval.
There are two steps to required to have TTL based timeout caching:
- In dispatcher.any file set enableTTL as 1 set
/enableTTL "1"
. - Create below OSGI configuration to set Max-Age, Daily, Weekly and Monthly to invalidate or clear cache.
OSGi Configurations
In your AEM Content project, create a sling:Folder
under your application’s /apps
folder.
Max Age
Create OSGI Configuration /apps/practice/osgiconfig/config/com.adobe.acs.commons.http.headers.impl.DispatcherMaxAgeHeaderFilter-paths-set-1.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="sling:OsgiConfig"
filter.pattern="[/content/practice/(.*)]"
max.age="60"/>
max.age
: Max age value (in seconds) to put in Cache Control header.
Daily
Create OSGI Configuration /apps/practice/osgiconfig/config/com.adobe.acs.commons.http.headers.impl.DispatcherMaxAgeHeaderFilter-paths-set-2.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="sling:OsgiConfig"
filter.pattern="[/content/practice/(.*)]"
expires.time="14:30"
/>
max.age
: Max age value (in seconds) to put in Cache Control header.expires.time
: Time of day which the content expires (HH:mm)
Weekly
Create OSGI Configuration /apps/practice/osgiconfig/config/com.adobe.acs.commons.http.headers.impl.DispatcherMaxAgeHeaderFilter-paths-set-3.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="sling:OsgiConfig"
filter.pattern="[/content/practice/(.*)]"
expires.time="14:30"
expires.day-of-week="Monday"
/>
max.age
: Max age value (in seconds) to put in Cache Control header.expires.time
: Time of day which the content expires (HH:mm)expires.day-of-week
: Day of week to expire the content. Allowed values:Monday
,Tuesday
,Wednesday
,Thursday
,Friday
,Saturday
,Sunday
.
Monthly
Create OSGI Configuration /apps/practice/osgiconfig/config/com.adobe.acs.commons.http.headers.impl.DispatcherMaxAgeHeaderFilter-paths-set-4.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="sling:OsgiConfig"
filter.pattern="[/content/site/locations/(.*)]"
expires.time="14:30"
expires.day-of-month="15"
/>
max.age
: Max age value (in seconds) to put in Cache Control header.expires.time
: Time of day which the content expires (HH:mm)expires.day-of-month
: Day of month to expire the content. Will expire on the closes day. Ex. If set to 31, in February will expire on the 28th (or 29th on leap-year).
Note
This feature expects that the Dispatcher was involved in the request chain. This expectation is managed via a known HTTP Header. To simulate the Dispatcher, add the necessary HTTP header to the request:
Server-Agent: Communique-Dispatcher
Imran Khan, Adobe Community Advisor, AEM certified developer and Java Geek, is an experienced AEM developer with over 11 years of expertise in designing and implementing robust web applications. He leverages Adobe Experience Manager, Analytics, and Target to create dynamic digital experiences. Imran possesses extensive expertise in J2EE, Sightly, Struts 2.0, Spring, Hibernate, JPA, React, HTML, jQuery, and JavaScript.