In my personal opinion, it is big task for everybody. Let me explain in details. Let’s consider a scenario where you want to move content from one AEM environment to another. The easy thing is to do to use AEM Package manager. That is good. And just build a package from one AEM, download it & install somewhere else. Easy process? You may think it is but it is not. From the Business perspective, the Package Manager tool totally sucks & for the following reasons:
Lack of basic features in Package Manager: There are many basic features missing. Some of them are:
- No way you can schedule the content package as a whole. And, if 100 pages to be scheduled then Each individual pages must be scheduled to replicate them.
- No way you could upload the individual pages content from one environment to another if individual pages are the parent pages in the content hierarchy. All the content has to be overridden.
- Not easy to revert the certain content if installed by the package manager. either whole content or nothing can be reverted.
Time-consuming & does not work in most of the cases: Downloading from one environment & uploading in another is very old fashion & time-consuming. For heavy content like size GB’s, It does not even work.
So, here are the list of possible Solutions:
Final Thought
I found it very easy in day to day work when you want to move the content here & there. However, if there is any confusion & question. leave a comment. will respond asap. thanks.
- TWC Grabbit is one of them. It was developed by one of our team members however not sure if it is working in all the AEM versions. It has so many dependencies & Needs to install & managed in source & destination. But it was a quite good one.
- AEM Package Manager Out of the box.
- Copy whole source CRX-QUICKSTART folder & override the destination: Not a feasible option if the content has to be moved to production from stage or from stage to prod. Also not a solution if you want to move the only fewer pages or images. However, Not bad solution for Dev & QA but comes with lots of maintenance once the content is overridden.
The most easiest way move content regularly
You need to have just two things: Have a servlet in source code & Configure destination replication agent. You can see below it.
Pros/Cons of this solution:
Hit this URL from a browser after your servlet & agent is done: http://localhost:4502/bin/support/content/publisher?path=etc/packages/abc.zip&destEnvName=QA&publishChildNodes=true. publishChildNodes is required when you want to publish child nodes also.
Agent Configuration in AEM Author
You need to have just two things: Have a servlet in source code & Configure destination replication agent. You can see below it.
Pros/Cons of this solution:
- First, a good thing is that it is pretty easy & you can replication any JCR path. Include a content package, one page/child pages, one image/set of images. if you replicate a content package then no need to install in the destination environment. And, Helpful when you just need some pages in your QA or dev from the stage. Not whole content.
- No dependency. No installation. Just one servlet, replication agent. And, using out of the box solutions.
- Pretty extensible. You can build fancy UI out of it & make it a tool out of it.
- Cross-environment replication & replication only for content movement. Any environment can be a source or destination. Having a separate replication agent just for copying content does not cause any replication queue issue.
- Cons is it is still using replication API & not any fancy third-party solution.
Hit this URL from a browser after your servlet & agent is done: http://localhost:4502/bin/support/content/publisher?path=etc/packages/abc.zip&destEnvName=QA&publishChildNodes=true. publishChildNodes is required when you want to publish child nodes also.
Agent Configuration in AEM Author
Replication authoring – Nothing different from other replication agent except Triggers configuration. Do the same as you see in the snapshot.
Replication Request Handler
Replication Request Handler
import com.day.cq.replication.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.http.HttpStatus;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Session;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Sample URL http://localhost:4502/bin/support/content/publisher?path=etc/packages/abc.zip&destEnvName=QA&publishChildNodes=true
*/
@SlingServlet (paths = "/bin/support/content/publisher",
methods = "GET", metatype = true, label = "Content publisher to publish content across environments")
public class PackagePublisher extends SlingAllMethodsServlet {
private static final Logger LOGGER = LoggerFactory.getLogger(PackagePublisher.class);
@Reference
private Replicator replicator;
private List<String> activatedPathsList;
@Override
public final void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws IOException {
String requestPath = request.getParameter("path");
String publishChildNodes = request.getParameter("publishChildNodes");
final String destEnvName = request.getParameter("destEnvName");
if (StringUtils.isNotBlank(requestPath) && StringUtils.isNotBlank(destEnvName)) {
activatedPathsList = new ArrayList<String>();
Session userSession = request.getResourceResolver().adaptTo(Session.class);
ReplicationOptions replicationOptions = new ReplicationOptions();
AgentFilter agentFilter = new AgentFilter() {
public boolean isIncluded(Agent agent) {
if(agent.getId().toLowerCase().contains(destEnvName.toLowerCase())) { return true;
}
return false;
}
};
replicationOptions.setFilter(agentFilter);
LOGGER.info("replication starting ");
try {
replicator.replicate(userSession, ReplicationActionType.ACTIVATE, requestPath, replicationOptions);
Resource childResource = request.getResourceResolver().getResource(requestPath);
if ("true".equalsIgnoreCase(publishChildNodes)) {
publishChildPages(childResource, userSession, replicationOptions);
}
for (String path: activatedPathsList){
LOGGER.info("Activate paths" + path );
}
response.setStatus(HttpStatus.SC_OK);
response.getWriter().print("given path is replicated to given environment. Check in destination env.");
} catch (ReplicationException e) {
response.setStatus(HttpStatus.SC_BAD_REQUEST);
response.getWriter().print("Check Parameters. Also check author replication agents for " + destEnvName);
e.printStackTrace();
}catch (Exception ex){
response.setStatus(HttpStatus.SC_BAD_REQUEST);
response.getWriter().print("Something was wrong!!");
}
} else{
response.setStatus(HttpStatus.SC_BAD_REQUEST);
response.getWriter().print("Parameters are not passed.");
}
}
private void publishChildPages(Resource childResource, Session userSession,
ReplicationOptions replicationOptions) throws ReplicationException {
if (childResource != null) {
Iterator<Resource> itr = childResource.listChildren();
while (itr.hasNext()) {
Resource temp = itr.next();
if (!temp.getPath().contains("rep:policy") && !temp.getPath().contains("jcr:content")) {
if (temp.hasChildren()) {
publishChildPages(temp, userSession, replicationOptions);
}
activatedPathsList.add(temp.getPath());
replicator.replicate(userSession, ReplicationActionType.ACTIVATE, temp.getPath(), replicationOptions);
}
}
}
}
}
Final Thought
I found it very easy in day to day work when you want to move the content here & there. However, if there is any confusion & question. leave a comment. will respond asap. thanks.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.