AEM Developer Series
- Day 00: AEM Developer Series
- Day 01: Introduction to AEM
- Day 02: AEM Architecture
- Day 03: Setting up AEM Development Environment
- Day 04: Developing First OSGi Bundle
- Day 05: Working with Sling Servlets in AEM
- Day 06: Playing with Sling Post Servlet
- Day 07: Creating your first component in AEM
- Day 08: Dueling with JavaScript Use API
- Day 09: Dueling with Java User API
- Day 10: Getting to know Sling Models
- Day 11: Client Libraries in Action
- Day 12: Creating your custom OSGi Configuration
- Day 13: Schedulers in AEM
- Day 14: Eventing in AEM
- Day 15: Custom Workflows in AEM
- Day 16: Creating JMX Beans in AEM
- Day 17: Working with QueryBuilder API
- Day 18: Working with Granite Datasources in AEM
- Day 19: Replication API in Action
- Day 20: Working with Users and Groups in AEM
AEM provides a rich Replication API which replicates the content from AEM Author to the AEM Publish instance. Though AEM provides out of the box Replication agents which are super easy to configure and provides much abstraction for the replication process, sometimes we are required to achieve this functionality programmatically such as when asset metadata is changed, or a page is versioned any many other cases.
In this post, we will see how can we replicate content programmatically. For this, we will be creating a Sling Servlet (how? see here) and passing the content path which we want to replicate as a query parameter. So without wasting much time, let's get our hands dirty with some code.
Replication by code
For using the Replication API, we will be using an API com.day.cq.replication.Replicator to replicate the content.
- Create a class named ReplicationServlet and paste the following code in it.
- First, we are getting the path of the path to be replicated as a request parameter.
- All we need to do is to define a field of the type com.day.cq.replication.Replicator, let OSGi injects the reference to Replicator service.
- The code is pretty simple as we are calling the replicate(Session session, ReplicationActionType type, String path) to replicate the content to the publish instance.
- But wait a minute? What about the assets that are referenced on the page? How do we replicate them? 🤔 We have an awesome class com.day.cq.dam.commons.util.AssetReferenceSearch that will get the reference of the Assets and replicate them as well. Pretty cool stuff, eh? 🙋.
- We pass page paths and assets paths and they are replicated one by one.
- After deploying the code, go to the browser and hit http://<host>:<port>/bin/demo/replication?contentPath=/content/we-retail/language-masters/en/user and see the content on the publish.
- The logs will look like this -
2018-10-19 22:34:10 - INFO - publish : Creating content for path /content/we-retail/language-masters/en/user
2018-10-19 22:34:11 - INFO - publish : Creating content for path /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : Sending POST request to http://localhost:4503/bin/receive?sling:authRequestLogin=1
2018-10-19 22:34:11 - INFO - publish : sent. Response: 200 OK
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Sending message to localhost:4503
2018-10-19 22:34:11 - INFO - publish : >> POST /bin/receive HTTP/1.0
2018-10-19 22:34:11 - INFO - publish : >> Action: Activate
2018-10-19 22:34:11 - INFO - publish : >> Path: /content/we-retail/language-masters/en/user
2018-10-19 22:34:11 - INFO - publish : >> Handle: /content/we-retail/language-masters/en/user
2018-10-19 22:34:11 - INFO - publish : >> Referer: about:blank
2018-10-19 22:34:11 - INFO - publish : >> ...spooling 2606 bytes...
2018-10-19 22:34:11 - INFO - publish : --
2018-10-19 22:34:11 - INFO - publish : << HTTP/1.1 200 OK
2018-10-19 22:34:11 - INFO - publish : << Date: Fri, 19 Oct 2018 17:04:11 GMT
2018-10-19 22:34:11 - INFO - publish : << X-Content-Type-Options: nosniff
2018-10-19 22:34:11 - INFO - publish : << Content-Type: text/plain;charset=utf-8
2018-10-19 22:34:11 - INFO - publish : << Content-Length: 30
2018-10-19 22:34:11 - INFO - publish : <<
2018-10-19 22:34:11 - INFO - publish : << ReplicationAction ACTIVATE ok.
2018-10-19 22:34:11 - INFO - publish : Message sent.
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Replication (ACTIVATE) of /content/we-retail/language-masters/en/user successful.
2018-10-19 22:34:11 - INFO - publish : Sending POST request to http://localhost:4503/bin/receive?sling:authRequestLogin=1
2018-10-19 22:34:11 - INFO - publish : sent. Response: 200 OK
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Sending message to localhost:4503
2018-10-19 22:34:11 - INFO - publish : >> POST /bin/receive HTTP/1.0
2018-10-19 22:34:11 - INFO - publish : >> Action: Activate
2018-10-19 22:34:11 - INFO - publish : >> Path: /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : >> Handle: /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : >> Referer: about:blank
2018-10-19 22:34:11 - INFO - publish : >> ...spooling 568041 bytes...
2018-10-19 22:34:11 - INFO - publish : --
2018-10-19 22:34:11 - INFO - publish : << HTTP/1.1 200 OK
2018-10-19 22:34:11 - INFO - publish : << Date: Fri, 19 Oct 2018 17:04:11 GMT
2018-10-19 22:34:11 - INFO - publish : << X-Content-Type-Options: nosniff
2018-10-19 22:34:11 - INFO - publish : << Content-Type: text/plain;charset=utf-8
2018-10-19 22:34:11 - INFO - publish : << Content-Length: 30
2018-10-19 22:34:11 - INFO - publish : <<
2018-10-19 22:34:11 - INFO - publish : << ReplicationAction ACTIVATE ok.
2018-10-19 22:34:11 - INFO - publish : Message sent.
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Replication (ACTIVATE) of /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg successful.
2018-10-19 22:34:11 - INFO - publish : Creating content for path /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : Sending POST request to http://localhost:4503/bin/receive?sling:authRequestLogin=1
2018-10-19 22:34:11 - INFO - publish : sent. Response: 200 OK
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Sending message to localhost:4503
2018-10-19 22:34:11 - INFO - publish : >> POST /bin/receive HTTP/1.0
2018-10-19 22:34:11 - INFO - publish : >> Action: Activate
2018-10-19 22:34:11 - INFO - publish : >> Path: /content/we-retail/language-masters/en/user
2018-10-19 22:34:11 - INFO - publish : >> Handle: /content/we-retail/language-masters/en/user
2018-10-19 22:34:11 - INFO - publish : >> Referer: about:blank
2018-10-19 22:34:11 - INFO - publish : >> ...spooling 2606 bytes...
2018-10-19 22:34:11 - INFO - publish : --
2018-10-19 22:34:11 - INFO - publish : << HTTP/1.1 200 OK
2018-10-19 22:34:11 - INFO - publish : << Date: Fri, 19 Oct 2018 17:04:11 GMT
2018-10-19 22:34:11 - INFO - publish : << X-Content-Type-Options: nosniff
2018-10-19 22:34:11 - INFO - publish : << Content-Type: text/plain;charset=utf-8
2018-10-19 22:34:11 - INFO - publish : << Content-Length: 30
2018-10-19 22:34:11 - INFO - publish : <<
2018-10-19 22:34:11 - INFO - publish : << ReplicationAction ACTIVATE ok.
2018-10-19 22:34:11 - INFO - publish : Message sent.
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Replication (ACTIVATE) of /content/we-retail/language-masters/en/user successful.
2018-10-19 22:34:11 - INFO - publish : Sending POST request to http://localhost:4503/bin/receive?sling:authRequestLogin=1
2018-10-19 22:34:11 - INFO - publish : sent. Response: 200 OK
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Sending message to localhost:4503
2018-10-19 22:34:11 - INFO - publish : >> POST /bin/receive HTTP/1.0
2018-10-19 22:34:11 - INFO - publish : >> Action: Activate
2018-10-19 22:34:11 - INFO - publish : >> Path: /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : >> Handle: /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg
2018-10-19 22:34:11 - INFO - publish : >> Referer: about:blank
2018-10-19 22:34:11 - INFO - publish : >> ...spooling 568041 bytes...
2018-10-19 22:34:11 - INFO - publish : --
2018-10-19 22:34:11 - INFO - publish : << HTTP/1.1 200 OK
2018-10-19 22:34:11 - INFO - publish : << Date: Fri, 19 Oct 2018 17:04:11 GMT
2018-10-19 22:34:11 - INFO - publish : << X-Content-Type-Options: nosniff
2018-10-19 22:34:11 - INFO - publish : << Content-Type: text/plain;charset=utf-8
2018-10-19 22:34:11 - INFO - publish : << Content-Length: 30
2018-10-19 22:34:11 - INFO - publish : <<
2018-10-19 22:34:11 - INFO - publish : << ReplicationAction ACTIVATE ok.
2018-10-19 22:34:11 - INFO - publish : Message sent.
2018-10-19 22:34:11 - INFO - publish : ------------------------------------------------
2018-10-19 22:34:11 - INFO - publish : Replication (ACTIVATE) of /content/dam/we-retail/en/experiences/arctic-surfing-in-lofoten/northern-lights.jpg successful.
Conclusion
Congratulations!! 🙋 today we saw a programmatic approach to the Replication API and published a page through it. I hope you enjoyed this post.
You can find the complete code of this project on my GitHub in this commit. Feel free to fork or open issues, if any.
I would love to hear your thoughts on this and would like to have suggestions from you to make it better.
Happy Coding 😊
Thanks for sharing this great and comprehensive article. Actually all your sharing are awesome!
ReplyDeleteI was wondering that why the replication is succeeded while I don't even have a publish instance running? What happened to those replications?
Thanks for the feedback. If your publish instance is not running then your payload will be accumulated in author instance's replication queue.
DeleteGreat Post. Thank you.
DeleteWhat is the difference between "ReplicationActionType.DEACTIVATE" and ReplicationActionType.DELETE?
And when to use those?
E.g.
If we delete a page from Author should we use DELETE ? or is it still ok to use DEACTIVATE
How to do the replication to another author instance, say author running on 4504?
ReplyDeleteTheoretically, you just have to configure your another author in the replication agent of the first author but there are some gotchas around this. This thread discusses all the things in more detail - https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/how-to-replicate-between-author-and-author-environment-in-cq5/qaq-p/192756
DeleteHow do we replicate the page with custom rollout config?
ReplyDelete@Reference
private Replicator replicator;
Replicator object is null.
Could you please elaborate question? If you don't want to use the custom config, then you can use out of the box replication in AEM.
DeleteHow do we replicate the page with custom rollout config?
ReplyDelete@Reference
private Replicator replicator;
Replicator object is null.
Error during replication of ReplicationAction{type=ACTIVATE, path[0]='/content/*', time=1621580417814, userId='**', revision='null'}: com.day.cq.replication.ReplicationException: GET can't have message body. Use POST or PUT .. As soon as i change the method type.. job started working.. How this method type is being configured ?
ReplyDeletehi , Is there any way to publish around 15000 assets via code as the above code fails after publishing around 4000 assets.
ReplyDeleteHi, Is there any way to publish around 15000 assets via code as the above code fails after publishing around 4000 assets
ReplyDelete