This tutorial will help us to clear servlet cache on publish of page or resource. We are going to use sling content distribution API to clear cache.
It is not a best practice to use custom code for invalidate cache explicitly. There are two custom ways we can clear cache using below API’s:
Sling content distribution module facilitates the distribution of Sling resources among various Sling instances. Operating at the path level, the API utilizes distribution agents to enable the transfer of specific paths between instances.
Sling content Distribution supports ADD, DELETE and INVALIDATE actions. Within the framework of Sling Content Distribution, cache invalidation is possible upon content publishing, removal, and even without triggering a publication event.
On Author mode, use EventHandler interface topic as com/day/cq/replication to invalidate cache on page publish/unpublish.
Note: Test above code in AEM as a cloud service environment not in local. This will not work in local.
package com.practice.core.utils;
import com.day.cq.replication.*;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.practice.core.constants.CommonConstants;
import com.practice.core.services.PracticeUserService;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.distribution.*;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
@Component(immediate = true, service = EventHandler.class, property = {
EventConstants.EVENT_TOPIC+"="+ReplicationAction.EVENT_TOPIC
})
public class InvalidateCacheEventHandler implements EventHandler {
// PracticeUserService will help us to fetch system user
@Reference
PracticeUserService practiceUserService;
// Distributor will help us to invalidate cache
@Reference
private Distributor distributor;
private static final Logger LOG = LoggerFactory.getLogger(InvalidateCacheEventHandler.class);
// Servlet path going to invalidate
private static final String servletPath = "/content/practice/ea/en/data/product.products.json";
public void handleEvent(Event event) {
ReplicationAction replicationAction = ReplicationAction.fromEvent(event);
ReplicationActionType replicationType = replicationAction.getType();
String agent = getAgentFromReplicationEvent(event);
LOG.info("Agent from event : {}", agent);
// Flush or invalidate cache if replication type is activate
if (replicationType.equals(ReplicationActionType.ACTIVATE)) {
try (ResourceResolver flushingResourceResolver = practiceUserService.getServiceResolver(
CommonConstants.PRACTICE_READ_CONTENT_ETC_GENERIC_LIST)) {
// Invalidate cache
invalidateCache(Arrays.asList(servletPath), agent,
DistributionRequestType.INVALIDATE, Boolean.TRUE, flushingResourceResolver);
} catch (Exception e) {
LOG.error("Replication exception occurred during Dispatcher Flush request.", e);
}
}
}
// Function will help us to get agent
private String getAgentFromReplicationEvent(Event event) {
if (Objects.nonNull(event)) {
List agentIds = (List) event.getProperty("agentIds");
String agent = (String) agentIds.get(0);
return Objects.nonNull(agent) ? agent : "publish";
}
return "publish";
}
private void invalidateCache(List<String> pathsToInvalidate, String agent,
DistributionRequestType requestType, Boolean isDeep, ResourceResolver resolver) {
// Invalidate cache for specific paths
DistributionRequest distributionRequest = new SimpleDistributionRequest(requestType,
isDeep, pathsToInvalidate.toArray(new String[0]));
if (!pathsToInvalidate.isEmpty()) {
// Invalidate cache using DistributionRequest
DistributionResponse distributionResponse = distributor.distribute(agent,
resolver, distributionRequest);
LOG.debug("Distribution Response: {}", distributionResponse);
LOG.debug("Distribution message: {}", distributionResponse.getMessage());
}
}
}
Allow JSON extension as part of /invalidate section under /cache as part of dispatcher configuration. It will allow us to clear cache for servlet having JSON as extension.
/0003 {
/glob "*.json"
/type "allow"
}
Replication API also allow us to clear cache on activation, deactivation and deletion of page.
The flush agent endpoint is not configurable but rather preconfigured to point to Dispatcher, matched with the publish service running alongside the flush agent.
The flush agent can typically be triggered by custom code based on OSGi events or workflows.
String[] paths = …
ReplicationOptions options = new ReplicationOptions();
options.setSynchronous(true);
options.setFilter( new AgentFilter {
public boolean isIncluded (Agent agent) {
return agent.getId().equals("flush");
}
});
Replicator.replicate (session,ReplicationActionType.DELETE,paths, options);
For Replication API also, allow JSON extension as part of /invalidate section under /cache as part of dispatcher configuration. It will allow us to clear cache for servlet having JSON as extension.
/0003 {
/glob "*.json"
/type "allow"
}
Specialist Master (Architect) with a passion for cutting-edge technologies like AEM (Adobe Experience Manager) and a proven track record of delivering high-quality software solutions.
📝 Blogs
javadoubts.com © All rights reserved