Skip to content

create post on how to create workflow step #31

@wildone

Description

@wildone

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;
}
}
}
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions