Content Fragments in Depth. CF Management Workflow. Part 3.4

Exadel Digital Experience Team Tech Tips May 31, 2023 5 min read

Since our previous article was aimed at describing rollout configuration, this snippet describes Content Fragments and Pages replication in AEM processes. An Author can check if instant replication is needed by ticking a corresponding checkbox. If so, another 2 Workflows are triggered – CF replication and ProxyPage replication.

Content Fragment Replication in AEM

Content Fragment replication WF path is set here:

var REPLICATE_WORKFLOW_CF_MODEL_ID = "/var/workflow/models/site/site-cf-replicate-workflow";
See more See less

Let’s have a look at this Workflow. It has only 1 step.

com.wcm.site.workflow.ReplicationWorkflow:

package com.wcm.site.workflow;
 
import com.adobe.acs.commons.util.WorkflowHelper;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import com.wcm.site.services.ReplicationService;
import com.wcm.site.util.LinkUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import static com.wcm.site.servlets.RolloutWorkflowStarter.SKIP_REPLICATION_AND_FLUSH_ARG_NAME;
import static com.wcm.site.workflow.WorkflowProcessBase.WORKFLOW_PROCESS_LABEL;
 
@Component(immediate = true, service = WorkflowProcess.class, property = {
        WORKFLOW_PROCESS_LABEL + "=Replication Workflow Process" })
public class ReplicationWorkflow extends CQWorkflowProcessBase implements WorkflowProcess {
 
    @Reference
    private WorkflowHelper workflowHelper;
 
    @Reference
    private ReplicationService replicationService;
 
    @Override
    public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap) {
        ResourceResolver resourceResolver = getResourceResolver(workflowHelper, workflowSession);
        List<string> pagePathsList = new ArrayList<>(Arrays.asList(getPersistedData(workItem, PAGE_PATHS_KEY_NAME, new String[]{})));
 
        boolean skipReplicationAndFlush = getPersistedData(workItem, SKIP_REPLICATION_AND_FLUSH_ARG_NAME, false);
        if (skipReplicationAndFlush) {
            return;
        }
        
        if (metaDataMap.containsKey("PROCESS_SPECIFIC_PAGE")) {
            String payload = workItem.getWorkflowData().getPayload().toString();
            pagePathsList.add(payload);
        }
 
        if (!pagePathsList.isEmpty()) {
            replicationService.publishOnly(resourceResolver, getPaths(resourceResolver, pagePathsList));
        }
    }
 
    private String[] getPaths(ResourceResolver resourceResolver, List<string> pagePathsList) {
        return pagePathsList.stream().map(path -> {
            String pathWithJcrContent = LinkUtils.appendJcrContentIfMissing(path);
            return resourceResolver.getResource(pathWithJcrContent) != null ?
                    pathWithJcrContent : path;
        }).toArray(String[]::new);
    }
}
</string></string>
See more See less

Proxy Page Replication in AEM

According to our clientlib js:

var REPLICATE_WORKFLOW_PAGE_MODEL_ID = "/var/workflow/models/site/replicate-proxy-page-workflow";
See more See less

Along with page replication, we should perform cache clearing. That’s why Proxy Page Replication WF has 2 processes: ReplicationWorkflow (the same as above) and Flush Cache Workflow Process.

com.wcm.site.workflow.FlushCacheWorkflow:

package com.wcm.site.workflow;
 
import com.adobe.acs.commons.util.WorkflowHelper;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import com.wcm.site.services.FlushExternalCacheService;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import static com.wcm.site.servlets.RolloutWorkflowStarter.SKIP_REPLICATION_AND_FLUSH_ARG_NAME;
import static org.apache.commons.lang3.ArrayUtils.nullToEmpty;
 
@Component(immediate = true, service = WorkflowProcess.class)
public class FlushCacheWorkflow extends CQWorkflowProcessBase implements WorkflowProcess {
 
   public static final String WILDCARD = "*";
  
   @Reference
   private WorkflowHelper workflowHelper;
 
   @Reference
   private FlushExternalCacheService flushExternalCacheService;
  
 
   @Override
   public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap) {
       List<string> pagePathsList = new ArrayList<>(Arrays.asList(nullToEmpty(getPersistedData(workItem, PAGE_PATHS_KEY_NAME, new String[]{}))));
       ResourceResolver resourceResolver = getResourceResolver(workflowHelper, workflowSession);
 
       boolean skipReplicationAndFlush = BooleanUtils.toBoolean(getPersistedData(workItem, SKIP_REPLICATION_AND_FLUSH_ARG_NAME, false));
       if (skipReplicationAndFlush) {
           return;
       }
      
       if (!pagePathsList.isEmpty()) {
           flushExternalCacheService.flushAll(pagePathsList.toArray(new String[0]), resourceResolver);
       }
   }
 
}
 
</string>
See more See less

We’re nearly done with the Content Fragment and replication in AEM flow. Stay tuned for the next vital step in our flow – Content Fragment Deactivation. Need help with your AEM implementation? Let us know.

Author: Iryna Ason

Was this article useful for you?

Get in the know with our publications, including the latest expert blogs