Integrate Akamai Cache Purge with AEM Servlet or Tool | Adobe Higher Education
Skip to main content
May 27, 2025
Beantwortet

Integrate Akamai Cache Purge with AEM Servlet or Tool

  • May 27, 2025
  • 5 Antworten
  • 1079 Ansichten

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!

Dieses Thema wurde für Antworten geschlossen.
Beste Antwort von giuseppebaglio

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.

5 Antworten

May 27, 2025

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!

SantoshSai
Community Advisor
Community Advisor
May 27, 2025
SantoshSai
Community Advisor
Community Advisor
May 27, 2025

Hi @shaik_hussainah,

1. Use: Akamai OPEN APIs with EdgeGrid authentication

Documentation: https://techdocs.akamai.com/purge-api/

You need:

Java Library (Recommended):

Use Akamai’s official EdgeGrid client:
https://github.com/akamai/AkamaiOPEN-edgegrid-java

2. Authentication Handling
Store credentials securely:
  • 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.

3. Access Control within AEM
  • 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.

4. Sample Code (Simple Version)

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());
        }
    }
}
Additional Resources

Hope that helps!

Santosh Sai
AmitVishwakarma
Community Advisor
Community Advisor
May 28, 2025

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:

giuseppebaglio
Level 10
May 28, 2025

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.

kautuk_sahni
Community Manager
Community Manager
July 1, 2025

@shaik_hussainah 

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!

Kautuk Sahni