Creating a custom Akamai replication agent in AEM

Adobe Experience Manager | AEM/CQ | Apache Sling

Creating a custom Akamai replication agent in AEM

Replication is central to the AEM experience. AEM is about content and replication is how you move that content across servers. You're most likely using at least two of the out-of-the-box replication agents provided by Adobe: your default agent activates content from author to publish and your dispatcher flush agent clears your Dispatcher cache. AEM provides several other replication agents for tasks such as replicating in reverse (publish to author), moving content within the Adobe Marketing Cloud products such as Scene 7 and Test and Target, and static agents for replicating to the file system. This blog post details the steps used to create your own custom replication agents.

Akamai replication agent selection dialog

The following sample project demonstrates a custom replication agent which purges Akamai CDN (Content Delivery Network) cached content. The full code for this blog is hosted on GitHub. There are three pieces to this project: the transport handler, the content builder, and the replication agent's user interface.

Transport Handler

TransportHandler implementations control the communication with the destination server and determines when to report back a positive ReplicationResult to complete the activation and when to report back a negative ReplicationResult returning the activation to the queue.



The default HTTP transport handler sends an authenticated request to the destination server specified in the "Transport URI" setting and expects an HTTP response with a status code of "200 OK" in order to mark the activation as successful. The Akamai CCU REST API responds with a status code of "201 Created" for a successful purge request. Therefore, a custom Transport Handler was utilized and given the responsibility for sending the POST requests, looking for 201 responses and returning the proper ReplicationResult.

The transport handler service determines which transport handler to use based on the overridden canHandle method. You'll notice that any replication agent configured with a "Transport URI" that begins with http:// or https:// will be handled by AEM's HTTP transport handler. The convention is to create a unique URL protocol/scheme and have your transport handler's canHandle method watch for Transport URIs that start with your URL scheme. For example, by navigating to a clean instance's Agents on Author page, you'll find default AEM replication agents using http://, static://, tnt://, s7delivery:// and repo://. In this example, the transport handler is activated on the amakai:// scheme and uses the hard coded Akamai API REST endpoint. A popular convention is to set your transport handler's Transport URIs that start with something like "foo-", which allows the user to configure their replication agent with either "foo-http://" or "foo-https://" and have your transport handler simply remove the custom prefix before making the HTTP request.

Akamai replication agent's Transport URI settings

The transport handler also handles other ReplicationActionTypes. The Akamai example implements the standard "Test Connection" feature of replication agents by making a GET request to the Akamai API endpoint which expects a "200 OK" response in return - it's simply testing the replication agent's configured username and password. The example does not implement other replication action types such as deletions, deactivations, and polling (reverse).

When you speak of a replication agent, you're first thought will probably be of the default agent that moves content from author to publish via HTTP. Likewise, I've been discussing the Akamai transport handler example and its usage of HTTP GET and POST requests. However, it's important to note that your transport handler doesn't need to make HTTP calls. For example, you can write an FTP transport handler or a transport handler that interacts with the server's file system like the static replication agent does. Your transport handler can do anything as long as it returns a positive or negative replication result to update the queue.

Content Builder

ContentBuilder implementations build the body of the replication request. Implementations of the ContentBuilder interface end up as serialization options in the replication agent configuration dialog along side the Default, Dispatcher Flush, Binary less, and Static Content Builder options.



The provided Akamai example project could have been done without implementing a content builder; the logic in the content builder could have been completed in the transport handler as the transport handler created it's own request anyways. Another thing to consider is whether you need the session as ContentBuilder implementations gives you that while TransportHandler implementations do not.

A perfect example of utilizing the content builder is in Andrew Khoury's Dispatcher refetching flush agent where the default HTTP transport handler is still used to communicate with the Dispatcher and only the HTTP request body needed to be built out in order for Dispatcher to fetch and re-cache content.

User Interface

By implementing a content builder, the user can simply use a default replication agent and choose the custom serialization type. However, the Akamai replication agent requires the following custom configurations:

  • an option to remove versus invalidate content
  • an option to purge resources versus purging via CP Codes
  • an option to purge the production versus staging domain
  • the reverse replication option removed

Akamai replication agent dialog set to purge CP codes

A clean user interface was provided in order for users to implement and configure the Akamai replication agent. To accomplish this, a custom cq:Template as well as a corresponding cq:Component including the view and dialog was made. The easiest way is to copy the default replication agent from /libs/cq/replication/templates/agent and /libs/cq/replication/components/agent to /apps/your-project/replication and update the agent like any other AEM component.

To keep things clean and simple, the Akamai replication agent component inherits from the default replication agent by setting the sling:resourceSuperType to cq/replication/components/agent. The only update needed to the copied component was the dialog options and the agent.jsp file as it contains JavaScript to open the dialog for which you need to update the path. Any additions to the dialog can be retrieved through the TransportContext's getConfig().getProperties() ValueMap.

72 comments

Ankur Chauhan | January 06, 2016 at 03:58 AM | Reply

Hi Nate, Thanks for this post.

Isaías Sosa | January 08, 2016 at 03:44 AM | Reply

Thank you for sharing, a lot of work on this post.

Imad ElAli | January 08, 2016 at 08:40 AM | Reply

Hi Nate, Excellent post indeed. Have you considered the case of multiple publish instances and the need to delay the flush until all dispatchers have been flushed ? Any thoughts on that? Thanks

Nate Yolles | January 21, 2016 at 05:21 PM | Reply

Hello Imad. These are certainly valid questions that need to be considered for your unique project. On my current project, we have custom workflows that trigger replication agents on the author instance for our Dispatchers and for Akamai. Since this method of activation isn't a part of our normal release path, the agents are set to "Ignore default" on the Agent Settings "Triggers" tab, and they're initiated programatically. We're not currently delaying the Akamai purge in any way and we haven't experienced any issues as of yet. You also want to think about your strategy holistically; do you need to purge Akamai on demand or could you rely on your Akamai TTL (time to live) settings?

Luo | January 22, 2016 at 08:36 PM | Reply

Looks like a clean and better implementation than even listener. When I activate a page there is often a list of DAM assets that need to go with the page. It looks to me like each asset is sent as a single request to Akamai. I thought it would be better if we queue up the requests and send as a batch to Akamai. Any thoughts?

Luo | January 22, 2016 at 08:40 PM | Reply

One more thing here: The template/component targets AEM6.1. A Sightly upgrade of the template and the component would be a lot cleaner.

Nate Yolles | February 25, 2016 at 02:59 AM | Reply

You could write your custom replication agent with Sightly if you choose. However, as of this writing replication in AEM has not been updated to the Touch UI; I only needed to overlay a single file in order to change a single line of JS, so I felt the work to convert to Sightly would be premature at this time.

EvanAEM | January 29, 2016 at 06:31 AM | Reply

Thanks Nate, So how ContentBuilder fits into your context. I assume you are not using it but putting it here as an addition to TransportHandler.

Nate Yolles | February 25, 2016 at 02:53 AM | Reply

In this example the ContentBuilder is being used to access the activated resources and add any vanity URLs to the purge/invalidation list. It's not necessarily needed as the behavior could take place in the TransportHandler if your desired. However, the ContentBuilder provides access to the session.

EvanAEM | January 29, 2016 at 08:17 AM | Reply

Also what would be trigger for this agent - manual or automatic? Automatic is what most use cases need.

Nate Yolles | February 25, 2016 at 02:50 AM | Reply

A custom replication agent can be triggered in the same manner as an other replication agent. Check/uncheck "Ignore default" in the agent settings and/or trigger the agent programmatically as usual.

Saravanan Dharmaraj | March 24, 2016 at 05:34 PM | Reply

Excellent post ...! Thanks

Ankur Mittal | March 30, 2016 at 05:37 PM | Reply

Hi Nate. Your replication agent has been very helpful for me so far. I am trying to fix a scenario where agent gets triggered with any sort of node deletions/activations/deactivations. e.g. When some node from etc is programmatically deleted from author, agent gets queued up with the deactivate request for same path, which should not happen. Any suggestions how that can be handled?

Nate Yolles | July 12, 2016 at 10:44 PM | Reply

Without knowing the full details of your application, one possible solution is to set your Akamai Replication Agent trigger to "Ignore default" and utilize a Replication Event Listener to programmatically replicate with the Akamai agent on activation of only certain nodes.

Mit | June 20, 2016 at 02:51 PM | Reply

Hi Nate, I tried using this custom agent. I'm getting below error : Error while building replication content java.lang.IllegalArgumentException: Could not find configuration for domain 'production' Any idea on what have I missed?

Vaibhav | July 06, 2016 at 12:57 AM | Reply

Did you got the solution for this issue? I am also getting the same issue not sure what I missed. Error : Error while building replication content java.lang.IllegalArgumentException: Could not find configuration for domain 'production'

Nate Yolles | July 12, 2016 at 10:34 PM | Reply

Please read lines 103-110 of the ContentBuilder implementation. In this demonstration I'm using the Externalizer service to create the full URL for Akamai to purge based off the resource path. You can replace that section of code with your own method, probably some string manipulation to concatenate the domain with the path, or you can configure the Externalizer service at http://localhost:4502/system/console/configMgr/com.day.cq.commons.impl.ExternalizerImpl with the "production" domain.

Josh | July 26, 2016 at 09:40 AM | Reply

Hi Nate, I got to know from Akamai that "REST CCU API will be deprecated soon - you need to update the library to use the new OPEN framework. " Will this agent work with OPEN as it is or some changes will require in OPEN framework?

Mit | August 03, 2016 at 08:59 AM | Reply

Hi Nate, While using this agent, the test connection gives 200 OK in response. But when I activate some resource, it shows blocked in queue with following logs: HttpResponseProxy{HTTP/1.1 403 Forbidden [Date: Wed, 03 Aug 2016 08:55:04 GMT, Server: Apache, Vary: Authorization, Content-Length: 192, Allow: GET, HEAD, POST, Keep-Alive: timeout=15, max=100, Connection: Keep-Alive, Content-Type: application/api-problem+json]} Can you please help me with this?

David | September 08, 2016 at 04:41 PM | Reply

Hey Nate, excellent work, thanks. I've seen you listed AEM 6.1 as a requirement. Do you see any reason this shouldn't work on 6.0, as we're tied to that in a current project of ours. I just tried installing it, but got a com.day.cq.replication.AgentNotFoundException: Replication triggered, but no agent found! when testing the connection. However, I am unsure if this is because of a msiconfiguration or incomaptibilities with 6.0 Thanks, David

Frank | September 30, 2016 at 02:12 AM | Reply

Hi Nate. This is great work! Your replication agent has been extremely helpful in helping my team develop a replication agent to replicate content metadata to a semantic database. The only issue we have come across is that the ContentBuilder's log messages sometimes do not appear in the replication log. Have you encountered this behavior before?

Upasana | June 29, 2017 at 03:18 PM | Reply

Great work Nate. This document has been very helpful.

Tushar | July 05, 2017 at 10:15 AM | Reply

Great Work Nate, but I wanted if you have tested the new fast purge feature of Akamai V3. If you could write something up to change the implementation for Akamai V3 using fast purge it will be a great help.

-- | March 14, 2018 at 11:46 AM | Reply

Comment removed by author.

Anand | July 13, 2018 at 03:19 PM | Reply

Hi, I want to add a checkbox at author to provide an option to invalidate or not invalidate at akamai. Is there any possible way to add a property at page level and read that property during replication.so that i am restrict the author to invalidate that page at akamai?

staletujzm | August 16, 2018 at 06:56 PM | Reply

<a href="http://missreplicawatches.com">cialis 5 mg</a> buy cheap cialis generic http://missreplicawatches.com

ptaletloso | August 16, 2018 at 08:21 PM | Reply

<a href="http://bullsac.com">levitra birth control</a> levitra versus cialis http://bullsac.com

btaletgbhy | August 16, 2018 at 09:37 PM | Reply

<a href="http://motechautomotive.com">cialis pill</a> canadian cialis online http://motechautomotive.com

ktaletvarr | September 10, 2018 at 10:05 PM | Reply

<a href="http://mphasset.com">best way to use viagra</a> difference between viagra and cialis http://mphasset.com

wtaletqyxj | September 10, 2018 at 10:35 PM | Reply

<a href="http://istanbulexpressonline.com">viagra coupon free trial</a> which is better cialis or viagra http://istanbulexpressonline.com

dtaletcysu | September 11, 2018 at 05:03 PM | Reply

<a href="http://istanbulexpressonline.com">cheap viagra sydney</a> generic viagra pills http://istanbulexpressonline.com

htaletwmgw | September 13, 2018 at 09:30 AM | Reply

<a href="http://gigawatt6.com">cheap cialis soft tabs</a> generic cialis india pharmacy http://gigawatt6.com

staletvhgz | September 13, 2018 at 06:16 PM | Reply

<a href="http://waltzweekend.com">order viagra softtabs</a> buy real viagra online cheap http://waltzweekend.com

ktaletuemj | September 15, 2018 at 10:44 AM | Reply

<a href="http://buycialisonl1ne.us">cheap cialis online</a> viagra cialis online http://buycialisonl1ne.us

btaletmyny | September 17, 2018 at 11:53 PM | Reply

<a href="http://istanbulexpressonline.com">cheap viagra paypal</a> generic viagra mail order http://istanbulexpressonline.com

dtaletvqkv | September 18, 2018 at 11:17 AM | Reply

<a href="http://buyviagraonl1ne.us">order viagra online india</a> generic viagra without prescription http://buyviagraonl1ne.us

vtaletdumm | September 18, 2018 at 10:02 PM | Reply

<a href="http://buyviagraonl1ne.us">viagra pills sale</a> buy viagra cheaply http://buyviagraonl1ne.us

jtaletotso | September 19, 2018 at 02:23 AM | Reply

<a href="http://missreplicawatches.com">buy cialis online prescription</a> order 5mg cialis online http://missreplicawatches.com

rtalethped | September 19, 2018 at 09:28 PM | Reply

<a href="http://buyviagraonl1ne.us">cheap viagra paypal</a> buy female viagra http://buyviagraonl1ne.us

gtaletgvmh | September 20, 2018 at 02:57 AM | Reply

<a href="http://canadian-pharmaonline.com">brand viagra cheap</a> mail order viagra canada http://canadian-pharmaonline.com

htaletcuof | September 20, 2018 at 01:41 PM | Reply

<a href="http://viciolatino.com">viagra canada</a> cheap viagra pills online http://viciolatino.com

wtaletugri | September 20, 2018 at 04:15 PM | Reply

<a href="http://h-m-j.com">viagra for men</a> cheap viagra canadian pharmacy http://h-m-j.com

qtalethwjm | September 20, 2018 at 08:02 PM | Reply

<a href="http://vico4me.com">cheap viagra 100mg</a> order pfizer viagra http://vico4me.com

rtaletikin | September 23, 2018 at 05:29 PM | Reply

<a href="http://canadian-pharmacyionline.com">generic viagra for sale</a> order generic viagra online http://canadian-pharmacyionline.com

rtaletqmic | September 23, 2018 at 11:52 PM | Reply

<a href="http://canadian-pharmabuy.com">best place to buy viagra</a> buy real viagra online cheap http://canadian-pharmabuy.com

ytaletoase | September 24, 2018 at 09:43 PM | Reply

<a href="http://canadian-pharmaonline.com">viagra prices</a> viagra from canada http://canadian-pharmaonline.com

ftaletauap | September 26, 2018 at 02:19 AM | Reply

<a href="http://buycialisonlineglka.com">cheapest generic cialis online</a> very cheap cialis http://buycialisonlineglka.com

ntaletequr | September 27, 2018 at 07:51 PM | Reply

<a href="http://timsbmw.com">levitra over the counter</a> viagra levitra cialis comparison http://timsbmw.com

vtaletcttx | September 28, 2018 at 01:24 AM | Reply

<a href="http://canadian-pharmakoani.com">purchase viagra online</a> cheap viagra no prescription http://canadian-pharmakoani.com

ztaletjvna | September 28, 2018 at 11:26 AM | Reply

<a href="http://canadian-pharmabuy.com">cheap viagra usa</a> buy viagra without a prescription http://canadian-pharmabuy.com

otaletzzgf | September 28, 2018 at 03:27 PM | Reply

<a href="http://canadian-pharmaorder.com">generic cialis without a prescription</a> cheap cialis overnight http://canadian-pharmaorder.com

italetxgif | September 30, 2018 at 03:47 AM | Reply

<a href="http://canadian-pharmasale.com">cialis generic canada pharmacy</a> order generic cialis http://canadian-pharmasale.com

ttaletvfsb | September 30, 2018 at 04:28 PM | Reply

<a href="http://canadian-pharmaonline.com">generic viagra for sale</a> cheap viagra in usa http://canadian-pharmaonline.com

gtaletfvzu | October 01, 2018 at 01:22 AM | Reply

<a href="http://canadian-pharmaorder.com">cheap generic cialis canadian pharmacy</a> generic cialis online pharmacy http://canadian-pharmaorder.com

ztaletysjl | October 01, 2018 at 08:35 PM | Reply

<a href="http://canadian-pharmabuy.com">order viagra uk</a> generic viagra online pharmacy england http://canadian-pharmabuy.com

utaleteqqn | October 02, 2018 at 05:29 AM | Reply

<a href="http://canadian-pharmabuy.com">generic viagra 100mg for sale</a> buy generic viagra online usa http://canadian-pharmabuy.com

ntaletkood | October 02, 2018 at 01:26 PM | Reply

<a href="http://canadian-pharmacyionline.com">cheap viagra pills for men</a> generic viagra soft tablets http://canadian-pharmacyionline.com

jtaletdflr | October 02, 2018 at 11:11 PM | Reply

<a href="http://rabbitinahat.com">cialis order online india</a> best place to buy generic cialis online http://rabbitinahat.com

gtaletghsu | October 03, 2018 at 07:21 PM | Reply

<a href="http://buyviagraonl1ne.us">order viagra online without a prescription</a> viagra 100mg price http://buyviagraonl1ne.us

vtaletgybl | October 04, 2018 at 01:50 AM | Reply

<a href="http://canadian-pharmacyionline.com">generic viagra 100mg prices</a> order generic viagra http://canadian-pharmacyionline.com

rtaletloue | October 04, 2018 at 11:12 AM | Reply

<a href="http://canadian-pharmacyibuy.com">discount cialis pills</a> generic cialis canada price http://canadian-pharmacyibuy.com

jtaletqtxd | October 06, 2018 at 10:44 PM | Reply

<a href="http://missreplicawatches.com">cheap cialis online uk shopping</a> buy cialis brand online usa http://missreplicawatches.com

otaletosvr | October 07, 2018 at 05:40 AM | Reply

<a href="http://canadian-pharmapills.com">cheap generic viagra from canada</a> buy viagra new york city http://canadian-pharmapills.com

vtaletaucy | October 08, 2018 at 09:13 PM | Reply

<a href="http://vico4me.com">buy cheap viagra usa</a> best online pharmacy for viagra http://vico4me.com

wtaletrzvn | October 11, 2018 at 09:12 PM | Reply

<a href="http://baymontelreno.com">buy cialis with prescription</a> buy brand cialis online http://baymontelreno.com

ttaletmnsf | October 12, 2018 at 05:34 AM | Reply

<a href="http://valladium.com">cialis pills sale</a> generic cialis http://valladium.com

ltaletdwos | October 12, 2018 at 01:12 PM | Reply

<a href="http://gigawatt6.com">where to buy cialis online forum</a> cialis side effects http://gigawatt6.com

ftaletzffn | October 13, 2018 at 04:01 AM | Reply

<a href="http://buycialisonlineglka.com">cialis cost</a> generic cialis pills http://buycialisonlineglka.com

staletwxxq | October 13, 2018 at 09:27 AM | Reply

<a href="http://gigawatt6.com">buy cialis new york</a> cheapest cialis usa http://gigawatt6.com

rtaletkidv | October 13, 2018 at 10:30 AM | Reply

<a href="http://viciolatino.com">generic viagra pills</a> buy viagra online cheap http://viciolatino.com

utaletzcfn | October 13, 2018 at 05:06 PM | Reply

<a href="http://rabbitinahat.com">buy 20 mg cialis online</a> buy cialis online without a prescription http://rabbitinahat.com

wtaletarti | October 14, 2018 at 09:23 AM | Reply

<a href="http://valladium.com">cheap cialis 5mg</a> cheap cialis canada http://valladium.com

Leave a Comment