Hi Community,
We currently purge Akamai cache manually using the Purge Cache option. We're looking to automate this by Integrating it into AEM either through a servlet or a custom tool.
The goal is: when we hit this servlet/tool, it should trigger Akamai cache purge for specific URLs.
Has anyone implemented this? Looking for:
Secure Akamai API integration tips.
Authentication handling
Access control within AEM
Any Sample code or resources
Thanks in advance!
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
hi @Shaik_HussainAh,
You can check out this repository: https://github.com/realgpp/aem-cdn-cache-invalidator.
You can create a servlet that utilizes the CdnInvalidationService; there are many configuration options available to customize it as needed.
Hi @Shaik_HussainAh,
Documentation: https://techdocs.akamai.com/purge-api/
You need:
client_token
client_secret
access_token
host
(e.g., https://akab-xxx.luna.akamaiapis.net
)
Use Akamai’s official EdgeGrid client:
https://github.com/akamai/AkamaiOPEN-edgegrid-java
In AEM OSGi Configurations
Or using Vault / environment variables in Cloud Manager
Example OSGi config:
@Property(label = "Akamai Host", value = "https://...")
String akamaiHost;
@Property(label = "Client Token")
String clientToken;
@Property(label = "Client Secret", passwordValue = "*****")
String clientSecret;
@Property(label = "Access Token")
String accessToken;
Use encrypted storage or secrets vaults when possible.
Create a permission-controlled servlet (e.g., /bin/purgeAkamai
)
Restrict access to specific groups or users (e.g., /bin
paths are typically restricted to authenticated users)
Use @SlingServletPaths
and check ResourceResolver.getUserID()
or user.hasRole("publish-purge")
etc.
Example:
if (!resourceResolver.isLive() || !user.hasPermission("purgeAkamai")) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
return;
}
Or use Adobe Granite Permissions or AEM ACLs.
Here’s a basic servlet outline that purges cache for given URLs:
@SlingServletPaths("/bin/purgeAkamai")
@Servlet(name = "Akamai Cache Purge Servlet", methods = "POST")
public class AkamaiPurgeServlet extends SlingAllMethodsServlet {
@Reference
private AkamaiConfigService akamaiConfigService; // Service that retrieves secure tokens
@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
String[] urls = request.getParameterValues("urls");
if (urls == null || urls.length == 0) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().write("No URLs provided.");
return;
}
try {
HttpClient client = HttpClientBuilder.create().build();
HttpPost purgeRequest = new HttpPost(akamaiConfigService.getHost() + "/ccu/v3/invalidate/url");
// Set headers using EdgeGrid signing (manual or with Akamai Java SDK)
purgeRequest.setHeader("Content-Type", "application/json");
String body = new Gson().toJson(Map.of("objects", urls));
purgeRequest.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
// Sign the request here with EdgeGrid
HttpResponse apiResponse = client.execute(purgeRequest);
response.setStatus(apiResponse.getStatusLine().getStatusCode());
response.getWriter().write(EntityUtils.toString(apiResponse.getEntity()));
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("Error: " + e.getMessage());
}
}
}
Adobe's Akamai Integration Guidelines (if any) - not official, but sometimes found in Experience League forums
Hope that helps!
Hi Community,
We currently purge Akamai cache manually using the Purge Cache option. We're looking to automate this by Integrating it into AEM either through a servlet or a custom tool.
The goal is: when we hit this servlet/tool, it should trigger Akamai cache purge for specific URLs.
Has anyone implemented this? Looking for:
Secure Akamai API integration tips.
Authentication handling
Access control within AEM
Any Sample code or resources
Thanks in advance!
Views
Replies
Total Likes
Hi @Shaik_HussainAh,
Similar question answered here: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/integrate-akamai-cache-pur...
Views
Replies
Total Likes
Hi @Shaik_HussainAh ,
Prerequisites
- Java 11+
- AEM 6.5 or AEMaaCS
- Akamai OPEN API credentials:
- host
- client_token
- client_secret
- access_token
Add this dependency to your core/pom.xml:
<dependency>
<groupId>com.akamai.edgegrid</groupId>
<artifactId>edgegrid-signer-apachehttpclient</artifactId>
<version>4.0.0</version>
</dependency>
Step 1: OSGi Config Interface (AkamaiConfigService)
@ObjectClassDefinition(name = "Akamai API Configuration")
public @interface AkamaiApiConfig {
@AttributeDefinition(name = "Host", description = "Akamai API base host")
String host();
@AttributeDefinition(name = "Client Token")
String clientToken();
@AttributeDefinition(name = "Client Secret")
String clientSecret();
@AttributeDefinition(name = "Access Token")
String accessToken();
}
@Component(service = AkamaiConfigService.class)
@Designate(ocd = AkamaiApiConfig.class)
public class AkamaiConfigService {
private String host;
private String clientToken;
private String clientSecret;
private String accessToken;
@Activate
@Modified
protected void activate(AkamaiApiConfig config) {
this.host = config.host();
this.clientToken = config.clientToken();
this.clientSecret = config.clientSecret();
this.accessToken = config.accessToken();
}
public EdgeGridRequestSigner getSigner() {
return EdgeGridRequestSigner.builder()
.host(host.replace("https://", ""))
.clientToken(clientToken)
.clientSecret(clientSecret)
.accessToken(accessToken)
.build();
}
public String getHost() {
return host;
}
}
Step 2: Secure Servlet to Purge Cache
@Component(service = Servlet.class,
property = {
"sling.servlet.methods=POST",
"sling.servlet.paths=/bin/akamai/purge"
})
public class AkamaiPurgeServlet extends SlingAllMethodsServlet {
@Reference
private AkamaiConfigService configService;
@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
if (!request.getResourceResolver().isLive()) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Unauthorized");
return;
}
String[] urls = request.getParameterValues("url");
if (urls == null || urls.length == 0) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No URLs provided.");
return;
}
// Prepare purge request
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(configService.getHost() + "/ccu/v3/invalidate/url");
post.setHeader("Content-Type", "application/json");
String jsonBody = new Gson().toJson(Collections.singletonMap("objects", urls));
post.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8));
// Sign the request
configService.getSigner().sign(post);
HttpResponse akamaiResponse = client.execute(post);
int statusCode = akamaiResponse.getStatusLine().getStatusCode();
String responseText = EntityUtils.toString(akamaiResponse.getEntity());
response.setStatus(statusCode);
response.getWriter().write(responseText);
}
}
Step 3: Curl or Postman Test
curl -X POST http://localhost:4502/bin/akamai/purge \
-u admin:admin \
-d "url=https://wwwstage.companyx.com/content/site/en/page1.html" \
-d "url=https://wwwstage.companyx.com/content/site/en/page2.html"
Note:
Restrict /bin/akamai/purge servlet via AEM permissions to admins or a dedicated group.
Don't expose this in publish unless required use author-only access for safety.
You can enhance further with Adobe Granite Token Auth, or shift this to a custom TouchUI/React tool inside the AEM admin console with CSRF tokens and validation.
Regards,
Amit
Views
Replies
Total Likes
hi @Shaik_HussainAh,
You can check out this repository: https://github.com/realgpp/aem-cdn-cache-invalidator.
You can create a servlet that utilizes the CdnInvalidationService; there are many configuration options available to customize it as needed.
Just checking in — were you able to resolve your issue?
We’d love to hear how things worked out. If the suggestions above helped, marking a response as correct can guide others with similar questions. And if you found another solution, feel free to share it — your insights could really benefit the community. Thanks again for being part of the conversation!
Views
Replies
Total Likes