-
-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Talk about
- why throttledTaskRunner
- PROCESS="design.aem.workflow.process.ContentFragmentPageGenerator"
- public @interface Config
- OSGI annotations, mention @Designate(ocd = ContentFragmentPageGenerator.Config.class)
_cq_dialog/.content.xml
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" jcr:title="Content Fragment Page Generation" sling:resourceType="cq/gui/components/authoring/dialog" extraClientlibs="[cq.workflow-util]"> <content granite:id="worfklow-processpayload" jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/tabs"> <items jcr:primaryType="nt:unstructured"> <common cq:hideOnEdit="true" jcr:primaryType="nt:unstructured" jcr:title="Common" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"/> <process cq:hideOnEdit="true" jcr:primaryType="nt:unstructured" jcr:title="Process" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"/> <processcommon jcr:primaryType="nt:unstructured" jcr:title="Common" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <basic jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> <items jcr:primaryType="nt:unstructured"> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" disabled="false" fieldLabel="Title" name="./jcr:title"/> <description jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textarea" disabled="false" fieldLabel="Description" name="./jcr:description"/> </items> </basic> <advanced jcr:primaryType="nt:unstructured" jcr:title="Advanced Settings" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> <items jcr:primaryType="nt:unstructured"> <advance jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/checkbox" fieldDescription="Check if your handler will advance to the next step." fieldLabel="Handler Advance" name="./metaData/PROCESS_AUTO_ADVANCE" text="Handler Advance" value="true"/> </items> </advanced> </items> </column> </items> </processcommon> <processargs jcr:primaryType="nt:unstructured" jcr:title="Config" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <advanced jcr:primaryType="nt:unstructured" jcr:title="Advanced" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> <items jcr:primaryType="nt:unstructured"> <throttle jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/form/select" fieldDescription="Process will throttle it self depending on system resources." fieldLabel="Throttle execution of page generation." name="./metaData/throttle" emptyOption="{Boolean}true" value=""> <items jcr:primaryType="nt:unstructured"> <true jcr:primaryType="nt:unstructured" text="Yes" value="true"/> <false jcr:primaryType="nt:unstructured" text="No" value="false"/> </items> </throttle> </items> </advanced> </items> </column> </items> </processargs> </items> </content> </jcr:root>
content.xml
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:description="Generate Pages for Content Fragments" jcr:primaryType="cq:Component" jcr:title="Content Fragment Page Generation" sling:resourceSuperType="cq/workflow/components/model/process" allowedParents="[*/parsys]" componentGroup="AEM.Design - Workflow"/>
_cq_editConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" cq:dialogMode="floating" cq:inherit="{Boolean}true" jcr:primaryType="cq:EditConfig"> <cq:formParameters jcr:description="Generate Pages for Content Fragments" jcr:primaryType="nt:unstructured" jcr:title="Content Fragment Page Generation" PROCESS="design.aem.workflow.process.ContentFragmentPageGenerator" PROCESS_AUTO_ADVANCE="true"/> </jcr:root>
TemplateProcess.java
`package design.aem.workflow.process;
import com.adobe.acs.commons.fam.ThrottledTaskRunner;
import com.adobe.acs.commons.util.WorkflowHelper;
import com.adobe.acs.commons.util.visitors.ContentVisitor;
import com.adobe.acs.commons.util.visitors.ResourceRunnable;
import com.adobe.acs.commons.workflow.WorkflowPackageManager;
import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.osgi.service.component.annotations.*;
import org.osgi.service.component.propertytypes.ServiceDescription;
import org.osgi.service.component.propertytypes.ServiceRanking;
import org.osgi.service.component.propertytypes.ServiceVendor;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Session;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@component(
immediate = true,
service = WorkflowProcess.class
)
@Designate(ocd = TemplateProcess.Config.class)
@ServiceDescription("Workflow step for generating pages for Content Fragments")
@ServiceRanking(1001)
@ServiceVendor("AEM.Design")
public class TemplateProcess implements WorkflowProcess {
@ObjectClassDefinition(
name = "AEM Design - Workflow - Content Fragment Page Generator",
description = "Workflow step for generating pages for Content Fragments"
)
public @interface Config {
@AttributeDefinition(
name = "Throttle",
description = "Throttle execution of workflow, default: true"
)
boolean throttle() default true;
}
private Config config;
private static final Logger LOGGER = LoggerFactory.getLogger(TemplateProcess.class);
protected static final String ARG_THROTTLE = "throttle";
@reference
private WorkflowHelper workflowHelper;
@reference
private WorkflowPackageManager workflowPackageManager;
@reference
private ResourceResolverFactory resourceResolverFactory;
@reference
private ThrottledTaskRunner throttledTaskRunner;
@activate
@Modified
protected void activate(Config config) {
LOGGER.info("activate: resourceResolverFactory={}", resourceResolverFactory);
this.config = config;
}
@deactivate
protected void deactivate(Config config) {
}
@OverRide
public final void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap) throws WorkflowException {
ResourceResolver resourceResolver = null;
final long start = System.currentTimeMillis();
try {
resourceResolver = workflowHelper.getResourceResolver(workflowSession);
final String originalPayload = (String) workItem.getWorkflowData().getPayload();
final List payloads = workflowPackageManager.getPaths(resourceResolver, originalPayload);
final ProcessArgs processArgs = new ProcessArgs(metaDataMap, config);
final AtomicInteger count = new AtomicInteger(0);
final AtomicInteger failCount = new AtomicInteger(0);
final Session session = resourceResolver.adaptTo(Session.class);
// Anonymous inner class to facilitate counting of processed payloads
final ResourceRunnable generatorRunnable = new ResourceRunnable() {
@OverRide
public void run(final Resource resource) throws Exception {
if (processArgs.isThrottle()) {
throttledTaskRunner.waitForLowCpuAndLowMemory();
}
//TODO: Add logic here
count.incrementAndGet();
}
private void failed(String message, Object... error) {
failCount.incrementAndGet();
LOGGER.error(message, error);
}
};
final ContentVisitor visitor = new ContentVisitor(generatorRunnable);
for (final String payload : payloads) {
final Resource resource = resourceResolver.getResource(payload);
if (!ResourceUtil.isNonExistingResource(resource)) {
visitor.accept(resource);
} else {
LOGGER.info("Payload does not exist: {}", payload);
}
}
if (failCount.get() == 0) {
session.save();
} else {
LOGGER.info("There were failures total of {} not saving", failCount.get());
}
LOGGER.error("Workflow step was execute [{}] times in {} ms", count.get(), System.currentTimeMillis() - start);
} catch (Exception e) {
LOGGER.error("Error occurred executing workflow.");
throw new WorkflowException(e);
}
}
/**
* ProcessArgs parsed from the Workflow metadata map.
*/
protected static class ProcessArgs {
private boolean throttle;
ProcessArgs(MetaDataMap map, Config config) throws WorkflowException {
// advanced config
if (map.get(ARG_THROTTLE, Boolean.class) == null) {
LOGGER.warn("Throttle not specified defaulting to throttle enabled.");
}
throttle = map.get(ARG_THROTTLE, config.throttle());
}
public boolean isThrottle() {
return throttle;
}
}
}
`