com.adobe.acs.samples.workflow.impl.SampleCQWorkflowProcess.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.acs.samples.workflow.impl.SampleCQWorkflowProcess.java

Source

/*
 * #%L
 * ACS AEM Samples
 * %%
 * Copyright (C) 2015 Adobe
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package com.adobe.acs.samples.workflow.impl;

import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.LoginException;
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.jcr.resource.JcrResourceConstants;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;
import java.util.Arrays;
import java.util.Collections;

/**
 *  This class is a copy of the SampleGraniteWorkflowProcess implementation however it uses the older CQ Workflow APIs,
 *  which are similar yet sufficiently different from the Granite Workflow APIs.
 *
 * Note the CQ and GraniteWorkflow APIs are NOT interchangeable, and do not have the same methods available to them.
 *
 * This implementation using the CQ Workflow APIs is considered the legacy approach.
 *
 * - CQ Workflow APIs: https://docs.adobe.com/docs/en/aem/6-1/ref/javadoc/com/day/cq/workflow/package-summary.html
 * - Granite Workflow APIs: https://docs.adobe.com/docs/en/aem/6-1/ref/javadoc/com/adobe/granite/workflow/package-summary.html
 */
@Component(label = "ACS AEM Samples - AEM CQ Workflow Process", description = "ACS AEM Samples - Sample CQ Workflow Process implementation")
@Properties({
        @Property(name = Constants.SERVICE_DESCRIPTION, value = "Sample CQ Workflow Process implementation.", propertyPrivate = true),
        @Property(label = "Workflow Label", name = "process.label", value = "Sample Workflow Process", description = "Label which will appear in the AEM Workflow interface; This should be unique across "
                + "Workflow Processes", propertyPrivate = true) })
@Service
public class SampleCQWorkflowProcess implements WorkflowProcess {
    private static final Logger log = LoggerFactory.getLogger(SampleCQWorkflowProcess.class);

    @Reference
    ResourceResolverFactory resourceResolverFactory;

    /**
     * The method called by the AEM Workflow Engine to perform Workflow work.
     *
     * @param workItem the work item representing the resource moving through the Workflow
     * @param workflowSession the workflow session
     * @param args arguments for this Workflow Process defined on the Workflow Model (PROCESS_ARGS, argSingle, argMulti)
     * @throws WorkflowException when the Workflow Process step cannot complete. This will cause the WF to retry.
     */
    @Override
    public final void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args)
            throws WorkflowException {

        /* Get the Workflow Payload */

        // Get the Workflow data (the data that is being passed through for this work item)

        final WorkflowData workflowData = workItem.getWorkflowData();
        final String type = workflowData.getPayloadType();

        // Check if the payload is a path in the JCR; The other (less common) type is JCR_UUID
        if (!StringUtils.equals(type, "JCR_PATH")) {
            return;
        }
        // Get the path to the JCR resource from the payload
        final String path = workflowData.getPayload().toString();

        /* Get Workflow Process Arguments */

        // These args are specified on the Workflow Model using this WF Process.

        /* Process Args */
        // These are free-form textfields; the values of these may need to be parsed based on
        // expected in put formats

        String processArgs = args.get("PROCESS_ARGS", "default value");
        String[] proccesArgsVals = StringUtils.split(processArgs, ",");

        /* Single and MultiValue args */

        // Some WF Process steps support Single and MultiValue args; these are can access via named properties
        // Custom WF inputs stored under ./metaData/argSingle and ./metadata/argMulti
        String singleValue = args.get("argSingle", "not set");
        String[] multiValue = args.get("argMulti", new String[] { "not set" });

        log.debug("Single Value: {}", singleValue);
        log.debug("Multi Value: {}", Arrays.toString(multiValue));

        /* Get data set in prior Workflow Steps */
        String previouslySetData = this.getPersistedData(workItem, "set-in-previous-workflow-step", String.class);

        /* Do work on the Payload; Remember to use Sling APIs as much as possible */

        ResourceResolver resourceResolver = null;
        try {
            // Get the ResourceResolver from workflow session
            resourceResolver = getResourceResolver(workflowSession.getSession());

            // Get the resource the payload points to; Keep in mind the payload can be any resource including
            // a AEM WF Package which must be processes specially.
            Resource resource = resourceResolver.getResource(path);

            // Do work ....

            // Save data for use in a subsequent Workflow step
            persistData(workItem, workflowSession, "set-for-next-workflow-step", "whatever data you want");

        } catch (Exception e) {
            // If an error occurs that prevents the Workflow from completing/continuing - Throw a WorkflowException
            // and the WF engine will retry the Workflow later (based on the AEM Workflow Engine configuration).

            log.error("Unable to complete processing the Workflow Process step", e);

            throw new WorkflowException("Unable to complete processing the Workflow Process step", e);
        }
    }

    /**
     * Helper methods.
     */

    private <T> boolean persistData(WorkItem workItem, WorkflowSession workflowSession, String key, T val) {
        WorkflowData data = workItem.getWorkflow().getWorkflowData();
        if (data.getMetaDataMap() == null) {
            return false;
        }

        data.getMetaDataMap().put(key, val);
        workflowSession.updateWorkflowData(workItem.getWorkflow(), data);

        return true;
    }

    private <T> T getPersistedData(WorkItem workItem, String key, Class<T> type) {
        MetaDataMap map = workItem.getWorkflow().getWorkflowData().getMetaDataMap();
        return map.get(key, type);
    }

    private <T> T getPersistedData(WorkItem workItem, String key, T defaultValue) {
        MetaDataMap map = workItem.getWorkflow().getWorkflowData().getMetaDataMap();
        return map.get(key, defaultValue);
    }

    private ResourceResolver getResourceResolver(Session session) throws LoginException {
        return resourceResolverFactory.getResourceResolver(Collections
                .<String, Object>singletonMap(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, session));
    }
}