Expand my Community achievements bar.

Submissions are now open for the 2026 Adobe Experience Maker Awards.
SOLVED

Integrate Akamai Cache Purge with AEM Servlet or Tool

Avatar

Level 1

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!

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Level 9

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.

View solution in original post

6 Replies

Avatar

Community Advisor

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

AEM BlogsLinkedIn


Avatar

Level 1

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!

Avatar

Community Advisor

Avatar

Community Advisor

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:

Avatar

Correct answer by
Level 9

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.

Avatar

Administrator

@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