Olet tarkastelemassa seuraavan version ohjesisältöä::

This topic describes how to develop custom step components for your workflows, then how to interact programmatically with workflows.

Creating a custom workflow step involves the following activities:

  • Develop the workflow step component.
  • Implement the step functionality as an OSGi service or an ECMA script. 

Workflow Step Components - The Basics

A workflow step component defines the appearance and behavior of the step when creating workflow models:

  • The category and step name in the workflow sidekick.
  • The appearance of the step in workflow models.
  • The edit dialog for configuring component properties.
  • The service or script that is executed at runtime.

As with all components, workflow step components inherit from the component that is specifed for the sling:resourceSuperType property. The following diagram shows the hierarchy of cq:component nodes that form the basis of all workflow step components. The diagram also includes the Process Step, Participant Step, and Dynamic Participant Step components, as these are the most common (and basic) starting points for developing custom step components. 

chlimage_1

Varoitus:

You must not change anything in the /libs path.

This is because the content of /libs is overwritten the next time you upgrade your instance (and may well be overwritten when you apply either a hotfix or feature pack).

The recommended method for configuration and other changes is:

1. Recreate the required item (i.e. as it exists in /libs) under /apps
2. Make any changes within /apps

The /libs/cq/workflow/components/model/step component is the nearest common ancestor of the Process Step, Participant Step, and Dynamic Participant Step, which all inherit the following items:

  • step.jsp

    The step.jsp script renders the title and description of the step component when it is added to a model. The default title and description are Double click to enter title and Double click to enter description, respectively.

    chlimage_1
  • details.jsp

    The details.jsp script renders the text that appears at the bottom of the step in the model editor. There is no detail text by default.

  • Dialog

    A dialog with the following tabs:

    • Common: for editing the title and description.
    • Advanced: for editing email notification properties.
    chlimage_1
    chlimage_1

    Huomautus:

    When the tabs of the edit dialog of a step component do not match this default appearance, the step component has defined scripts, node properties, or dialog tabs that override these inherited tabs.

ECMA Scripts

The following objects are available (dependent on step type) within ECMA scripts:

MetaDataMaps

You can use workflow metadata to persist information that is required during the lifetime of the workflow. A common requirement of workflow steps is to persist data for future use in the workflow, or to retrieve the persisted data. 

There are three types of MetaDataMap objects - for Workflow, WorkflowData and WorkItem objects. They all have the same intended purpose – to store metadata.

A WorkItem has its own MetaDataMap that can be only used while that workitem (e.g. step) is running.

Both Workflow and WorkflowData metadatamaps are shared over the entire workflow. For these cases it is recommended to only use the WorkflowData metadata map.

Creating Custom Workflow Step Components

Workflow step components can be created in the same manner as any other component.

Huomautus:

As the Workflow Model Editor is only available in the Classic UI, your workflow step components must be developed for the Classic UI.

To inherit from one of the (existing) base step components, add the following property to the cq:Component node:

  • Name: sling:resourceSuperType
  • Type: String
  • Value: One of the following paths that resolves to a base component:
    • cq/workflow/components/model/process
    • cq/workflow/components/model/participant
    • cq/workflow/components/model/dynamic_participant

Specifying the Default Title and Description for Step Instances

In the workflow model editor, the graphical representation of a step includes the title and description that are stored with the step instance. The title and description are retrieved from the Title and Description fields on the Common tab of the Edit dialog. However, when an instance does not have values for Title or Description, the following default text appears instead:

  • Double-click to enter title.
  • Double-click to enter description.
chlimage_1

Use the following procedure to specify default values for the Title and Description fields on the Common tab.

Huomautus:

The field values appear on the step instance when both of the following requirements are satisfied:

  • The edit dialog of the step stores the title and description in the following locations:
    • ./jcr:title
    • ./jcr:description locations
    This requirement is satisfied when the edit dialog uses the Common tab that the /libs/cq/flow/components/step/step component implements.
  • The step component or an ancestor of the component does not override the step.jsp script that the /libs/cq/flow/components/step/step component implements.

  1. Below the cq:Component node, add the following node:

    • Name: cq:editConfig
    • Type: cq:EditConfig

    Huomautus:

    For more information about the cq:editConfig node, see Configuring the Edit Behaviour of a Component.

  2. Below the cq:EditConfig node, add the following node:

    • Name: cq:formParameters
    • Type: nt:unstructured
  3. Add String properties of the following names to the cq:formParameters node:

    • jcr:title: The value fills the Title field of the Common tab.
    • jcr:description: The value fills the Description field of the Common tab.

Adding Detailed Information for Step Instances

Add detailed information that appears on the step instance when it is added to a workflow model.

Huomautus:

To see an example of this configuration, use CRXDE Lite to explore the /libs/cq/workflow/components/model/process component.

Huomautus:

The following procedure requires that the step component, or an ancestor of the component, does not override the step.jsp script that the /libs/cq/flow/components/step/step component implements.

  1. Add the following node below the cq:Component node:

    • Name: details.jsp
    • Type: nt:file
  2. Edit the details.jsp file so that it generates the detailed information as HTML code.  

Saving Property Values in Workflow Metadata

Huomautus:

See Persisting and Accessing Data. In particular, for information about accessing the property value at runtime, see Accessing Dialog Property Values at Runtime.

The name property of cq:Widget items specifies the JCR node that stores the widget's value. When widgets in the dialog of workflow step compnents store values below the ./metaData node, the value is added to the workflow MetaDataMap

For example, a text field in a dialog is a cq:Widget node that has the following properites:

Name Type Value
xtype String textarea
name String ./metaData/subject
fieldLabel String Email Subject

The value that is specified in this text field is added to the workflow instance's MetaDataMap object, and is associated with the subject key. 

Huomautus:

When the key is PROCESS_ARGS, the value is readily available in ECMA script implementations via the args variable. In this case, the value of the name property is ./metaData/PROCESS_ARGS.

Overriding the Step Implementation

Each base step component enable workflow model developers to configure the following key features  at design time:

  • Process Step: The service or ECMA script to execute at runtime. 
  • Participant Step: The ID of the user that is assigned the generated work item. 
  • Dynamic Participant Step: The service or ECMA script that selects the ID of the user that is assigned the work item.

To focus the component for use in a specific workflow scenario, configure the key feature in the design and remove the ability for model developers to change it.

  1. Below the cq:component node, add the following node:

    • Name: cq:editConfig
    • Type: cq:EditConfig

    For more information about the cq:editConfig node, see Configuring the Edit Behaviour of a Component.

  2. Below the cq:EditConfig node, add the following node:

    • Name: cq:formParameters
    • Type: nt:unstructured
  3. Add a String property to the cq:formParameters node. The component super type determines the name of the property:

    • Process Step: PROCESS
    • Participant Step: PARTICIPANT
    • Dynamic Participant Step: DYNAMIC_PARTICIPANT
  4. Specify the value of the property:

    • PROCESS: The path to the ECMA script or the PID of the service that implements the step behavior.
    • PARTICIPANT: The ID of the user who is assigned the work item.
    • DYNAMIC_PARTICIPANT: The path to the ECMA script or the PID of the service that selects the user to assign the work item.
  5. To remove the ability of model developers to change your property values, override the dialog of the component super type. Define a dialog for the component as described in Overriding the Edit Dialog.

Adding Forms and Dialogs to Participant Steps

Customize your participant step component to provide features that are found in the Form Participant Step and Dialog Participant Step components:

  • Present a form to the user when they open the generated work item. 
  • Present a custom dialog to the user when they complete the generated work item.

Peform the following procedure on your new component (see Creating Custom Workflow Step Components):

  1. Below the cq:Component node, add the following node:

    • Name: cq:editConfig
    • Type: cq:EditConfig

    For more information about the cq:editConfig node, see Configuring the Edit Behaviour of a Component.

  2. Below the cq:EditConfig node, add the following node:

    • Name: cq:formParameters
    • Type: nt:unstructured
  3. To present a form when the user opens the work item, add the following property to the cq:formParameters node:

    • Name: FORM_PATH
    • Type: String
    • Value: The path that resolves to the form
  4. To present a custom dialog when the user completes the work item, add the following property to the cq:formParameters node

    • Name: DIALOG_PATH
    • Type: String
    • Value: The path that resolves to the dialog

Configuring the Workflow Step Runtime Behavior

Below the cq:Component node, add a cq:EditConfig node. Below that add an nt:unstructured node (must be named cq:formParameters) and to that node add the following properties:

  • Name: PROCESS_AUTO_ADVANCE 
  • Type: Boolean
  • Value: 
    • when set to true the workflow will run that step and continue - this is default and also recommended
    • when false, the workflow will run and stop; this needs extra handling, so true is recommended

 

  • Name: DO_NOTIFY
  • Type: Boolean
  • Value: indicates whether email notifications should be sent for user participation steps (and assumes that the mail server is correctly configured)

Persisting and Accessing Data

Persisting Data for Subsequent Workflow Steps

You can use workflow metadata to persist information that is required during the lifetime of the workflow - and between steps. A common requirement of workflow steps is to persist data for future use, or to retrieve the persisted data from prior steps. 

Workflow metadata is stored in a MetaDataMap object. The Java API provides the Workflow.getWorkflowData method to return a WorkflowData object that provides the appropriate MetaDataMap object. This WorkflowData MetaDataMap object is available to the OSGi service or ECMA script of a step component.

Java

The execute method of the WorkflowProcess implementation is passed the WorkItem object. Use this object to obtain the WorkflowData object for the current workflow instance. The following example adds an item to the workflow MetaDataMap object and then logs each item. The ("mykey", "My Step Value") item is available to subsequent steps in the workflow.

public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
    	
    MetaDataMap wfd = item.getWorkflow().getWorkflowData().getMetaDataMap();

    wfd.put("mykey", "My Step Value");
    	
    Set<String> keyset = wfd.keySet();
    Iterator<String> i = keyset.iterator();
    while (i.hasNext()){
    	Object key = i.next();
    	log.info("The workflow medata includes key {} and value {}",key.toString(),wfd.get(key).toString());
    }
}

ECMA Script

The graniteWorkItem variable is the ECMA script representation of the current WorkItem Java object. Therefore, you can use the graniteWorkItem variable to obtain the workflow metadata. The following ECMA script can be used to implement a Process Step to add an item to the workflow MetaDataMap object and then log each item. These items are then available to subsequent steps in the workflow.

Huomautus:

The metaData variable that is immediately available to the step script is the metadata of the step. The step metadata is different from the workflow metadata.

var currentDateInMillis = new Date().getTime();

graniteWorkItem.getWorkflowData().getMetaDataMap().put("hardcodedKey","theKey");

graniteWorkItem.getWorkflowData().getMetaDataMap().put("currentDateInMillisKey",currentDateInMillis);

var iterator = graniteWorkItem.getWorkflowData().getMetaDataMap().keySet().iterator();
while (iterator.hasNext()){
    var key = iterator.next();
    log.info("Workflow metadata key, value = " + key.toString() + ", " + graniteWorkItem.getWorkflowData().getMetaDataMap().get(key));
}

Accessing Dialog Property Values at Runtime

The MetaDataMap object of workflow instances is useful for storing and retrieving data throughout the lifetime of the workflow. For workflow step components implementations, the MetaDataMap is especially useful for retrieving component property values at runtime.

Huomautus:

For information about configuring the component dialog to store properties as workflow metadata, see Saving Property Values in Workflow Metadata.

The workflow MetaDataMap is available to Java and ECMA script process implementations:

  • In Java implementations of the WorkflowProcess interface, the args parameter is the MetaDataMap object for the workflow. 
  • In  ECMA script implementations, the value is available using the args and metadata variables. 

Example: Retrieving the Arguments of the Process Step Component

The edit dialog of the Process Step component includes the Arguments property. The value of the Arguments property is stored in the worklow metadata, and is associated with the PROCESS_ARGS key.

In the following diagram, the value of the Arguments property is argument1, argument2:

Java

The following Java code is the execute method for a WorkflowProcess implementation. The method logs the value in the args MetaDataMap that is associated with the PROCESS_ARGS key.

public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
    	if (args.containsKey("PROCESS_ARGS")){
    		log.info("workflow metadata for key PROCESS_ARGS and value {}",args.get("PROCESS_ARGS","string").toString());
    	}    	
    }

When a process step that uses this Java implementation executes, the log contains the following entry:

16.02.2017 12:07:39.566 *INFO* [JobHandler: /etc/workflow/instances/2017-02-16/model_855140139900189:/content/we-retail/de] com.adobe.example.workflow.impl.process.LogArguments workflow metadata for key PROCESS_ARGS and value argument1, argument2

ECMA Script

The following ECMA script is used as the process for the Process Step. It logs the number of arguments and the argument values:

var iterator = graniteWorkItem.getWorkflowData().getMetaDataMap().keySet().iterator();
while (iterator.hasNext()){
    var key = iterator.next();
    log.info("Workflow metadata key, value = " + key.toString() + ", " + graniteWorkItem.getWorkflowData().getMetaDataMap().get(key));
}
log.info("hardcodedKey "+ graniteWorkItem.getWorkflowData().getMetaDataMap().get("hardcodedKey"));
log.info("currentDateInMillisKey "+ graniteWorkItem.getWorkflowData().getMetaDataMap().get("currentDateInMillisKey"));

Huomautus:

This section describes how to work with arguments for process steps. The information also applies to dynamic participant choosers.

 

Huomautus:

For another example of storing component properties in workflow metadata, see Example: Create a Logger Workflow Step. This example features a dailog that associates metadata value with a key other than PROCESS_ARGS.

Scripts and Process Arguments

Within a script for a Process Step component, arguments are available through the args object.

When creating a custom step component, the object metaData is available in a script. This object is limited to a single string argument. 

Developing Process Step Implementations

When process steps are started during the process of a workflow, the steps send a request to an OSGi service or execute an ECMA script. Develop the service or ECMA script that performs the actions that your workflow requires.

Huomautus:

For information about associating your Process Step component with the service or script, see Process Step or Overriding the Step Implementation.

Implementing a Process Step with a Java Class

To define a process step as an OSGI service component (Java bundle):

  1. Create the bundle and deploy it into the OSGI container. Refer to the documentation about creating a bundle with CRXDE Lite or Eclipse.

    Huomautus:

    The OSGI component needs to implement the WorkflowProcess interface with its execute() method. See the example code below.

    Huomautus:

    The package name needs to be added to the <Private-Package> section of the maven-bundle-plugin configuration.

  2. Add the SCR property process.label  and set the value as you require. This will be the name which your process step is listed as when using the generic Process Step component. See the example below.

  3. In the Models editor, add the process step to the workflow using the generic Process Step component.

  4. In the edit dialog (of the Process Step), go to the Process tab and select your process implementation. 

  5. If you use arguments in your code, set the Process Arguments. For example: false.

  6. Save the changes, for both the step and the workflow model (top left corner of the model editor).

The java methods, respectively the classes that implement the executable Java method are registered as OSGI services, enabling you to add methods at anytime during runtime.

The following OSGI component adds the property approved to the page content node when the payload is a page:

package com.adobe.example.workflow.impl.process;

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.WorkflowData;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;

import org.osgi.framework.Constants;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

/**
 * Sample workflow process that sets an <code>approve</code> property to the payload based on the process argument value.
 */
@Component
@Service
public class MyProcess implements WorkflowProcess {

	@Property(value = "An example workflow process implementation.")
	static final String DESCRIPTION = Constants.SERVICE_DESCRIPTION; 
	@Property(value = "Adobe")
	static final String VENDOR = Constants.SERVICE_VENDOR;
	@Property(value = "My Sample Workflow Process")
	static final String LABEL="process.label";


	private static final String TYPE_JCR_PATH = "JCR_PATH";

	public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
		WorkflowData workflowData = item.getWorkflowData();
		if (workflowData.getPayloadType().equals(TYPE_JCR_PATH)) {
			String path = workflowData.getPayload().toString() + "/jcr:content";
			try {
				Session jcrSession = session.adaptTo(Session.class); 
				Node node = (Node) jcrSession.getItem(path);
				if (node != null) {
					node.setProperty("approved", readArgument(args));
					jcrSession.save();
				}
			} catch (RepositoryException e) {
				throw new WorkflowException(e.getMessage(), e);
			}
		}
	}

	private boolean readArgument(MetaDataMap args) {
		String argument = args.get("PROCESS_ARGS", "false");
		return argument.equalsIgnoreCase("true");
	}
}

Huomautus:

If the process fails three times in a row, an item is placed in the Inbox of the workflow administrator.

Using ECMAScript

ECMA scripts enable script developers to implement process steps. The scripts are located in the JCR repository and executed from there.

The following table lists the variables that are immediately available to process scripts, providing access to objects of the workflow Java API.

Java Class Script variable name Description
com.adobe.granite.workflow.exec.WorkItem graniteWorkItem The current step instance.
com.adobe.granite.workflow.WorkflowSession graniteWorkflowSession The workflow session of the current step instance.
String[] (contains process arguments) args The step arguments.
com.adobe.granite.workflow.metadata.MetaDataMap metaData The meta data of the current step instance.
org.apache.sling.scripting.core.impl.InternalScriptHelper sling Provides access to the Sling runtime environment.

The following example script demonstrates how to access the JCR node that represents the workflow payload. The graniteWorkflowSession variable is adapted to a JCR session variable, which is used to obtain the node from the payload path.

var workflowData = graniteWorkItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") { 
    var path = workflowData.getPayload().toString(); 
    var jcrsession = graniteWorkflowSession.adaptTo(Packages.javax.jcr.Session);
    var node = jcrsession.getNode(path);
    if (node.hasProperty("approved")){
    	node.setProperty("approved", args[0] == "true" ? true : false);
    	node.save();
	}
}

The following script checks if the payload is an image (.png file), creates a black and white image from it, and saves it as a sibling node.

var workflowData = graniteWorkItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") { 
    var path = workflowData.getPayload().toString(); 
    var jcrsession = graniteWorkflowSession.adaptTo(Packages.javax.jcr.Session);
    var node = jcrsession.getRootNode().getNode(path.substring(1));
     if (node.isNodeType("nt:file") && node.getProperty("jcr:content/jcr:mimeType").getString().indexOf("image/") == 0) { 
        var is = node.getProperty("jcr:content/jcr:data").getStream();
        var layer = new Packages.com.day.image.Layer(is);
        layer.grayscale();
                var parent = node.getParent();
                var gn = parent.addNode("grey" + node.getName(), "nt:file"); 
        var content = gn.addNode("jcr:content", "nt:resource");
                content.setProperty("jcr:mimeType","image/png");
                var cal = Packages.java.util.Calendar.getInstance();
                content.setProperty("jcr:lastModified",cal);
                var f = Packages.java.io.File.createTempFile("test",".png");
        var tout = new Packages.java.io.FileOutputStream(f);
        layer.write("image/png", 1.0, tout);
        var fis = new Packages.java.io.FileInputStream(f);
                content.setProperty("jcr:data", fis);
                parent.save();
        tout.close();
        fis.close();
        is.close();
        f.deleteOnExit();
    }
}

To use the script:

  1. Create the script (for example with CRXDE Lite) and save it in the repository below /etc/workflow/scripts

  2. To specify a title that identifies the script in the Process Step edit dialog, add the following properties to the jcr:content node of your script:

    Name Type Value
    jcr:mixinTypes Name[] mix:title
    jcr:title String The name to appear in the edit dialog.
  3. Edit the Process Step instance and specify the script to be used.

Developing Participant Choosers

You can develop participant choosers for Dynamic Participant Step components.

When a Dynamic Participant Step component is started during a workflow, the step needs to detemine the participant to which the generated work item can be assigned. To do this the step either:

  • sends a request to an OSGi service 
  • executes an ECMA script to select the participant

You can develop a service or ECMA script that selects the participant according to the requirements of your workflow.

Huomautus:

For information about associating your Dynamic Participant Step component with the service or script, see Dynamic Participant Step or Overriding the Step Implementation.

Developing a Participant Chooser Using a Java class

To define a participant step as an OSGI service component (Java class):

  1. The OSGI component needs to implement the ParticipantStepChooser interface with its getParticipant() method. See the example code below.

    Create the bundle and deploy it into the OSGI container.

  2. Add the SCR property chooser.label and set the value as required. This will be the name as which your participant chooser is listed, using the Dynamic Participant Step component. See the example:

    package com.adobe.example.workflow.impl.process;
    
    import com.adobe.granite.workflow.WorkflowException;
    import com.adobe.granite.workflow.WorkflowSession;
    import com.adobe.granite.workflow.exec.ParticipantStepChooser;
    import com.adobe.granite.workflow.exec.WorkItem;
    import com.adobe.granite.workflow.exec.WorkflowData;
    import com.adobe.granite.workflow.metadata.MetaDataMap;
    
    import org.apache.felix.scr.annotations.Component;
    import org.apache.felix.scr.annotations.Property;
    import org.apache.felix.scr.annotations.Service;
    
    import org.osgi.framework.Constants;
     
    /**
     * Sample dynamic participant step that determines the participant based on a path given as argument.
     */
    @Component
    @Service
    
    public class MyDynamicParticipant implements ParticipantStepChooser {
    	
    	@Property(value = "An example implementation of a dynamic participant chooser.")
    	static final String DESCRIPTION = Constants.SERVICE_DESCRIPTION; 
        @Property(value = "Adobe")
        static final String VENDOR = Constants.SERVICE_VENDOR;
        @Property(value = "Dynamic Participant Chooser Process")
        static final String LABEL=ParticipantStepChooser.SERVICE_PROPERTY_LABEL;
     
        private static final String TYPE_JCR_PATH = "JCR_PATH";
     
        public String getParticipant(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args) throws WorkflowException {
            WorkflowData workflowData = workItem.getWorkflowData();
            if (workflowData.getPayloadType().equals(TYPE_JCR_PATH)) {
                String path = workflowData.getPayload().toString();
                String pathFromArgument = args.get("PROCESS_ARGS", String.class);
                if (pathFromArgument != null && path.startsWith(pathFromArgument)) {
                    return "admin";
                }
            }
            return "administrators";
        }
    }
  3. In the Models editor, add the dynamic participant step to the workflow using the generic Dynamic Participant Step component.

  4. In the edit dialog select the Participant Chooser tab and select your chooser implementation.

  5. If  you use arguments in your code set the Process Arguments. For this example: /content/we-retail/de.

  6. Save the changes, for both the step and the workflow model.

Developing a Participant Chooser Using an ECMA Script

You can create an ECMA script that selects the user that is assigned the work item that the Participant Step generates. The script must include a function named getParticipant that requires no argumemts, and returns a String that contains the ID of a user or group.

Scripts are located in the JCR repository and executed from there.

The following table lists the variables that provide immediate access to workflow Java objects in your scripts.

Java Class Script variable name
com.adobe.granite.workflow.exec.WorkItem graniteWorkItem
com.adobe.granite.workflow.WorkflowSession graniteWorkflowSession
String[] (contains process arguments) args
com.adobe.granite.workflow.metadata.MetaDataMap metaData
org.apache.sling.scripting.core.impl.InternalScriptHelper sling
function getParticipant() {
    var workflowData = graniteWorkItem.getWorkflowData();
    if (workflowData.getPayloadType() == "JCR_PATH") { 
        var path = workflowData.getPayload().toString(); 
        if (path.indexOf("/content/we-retail/de") == 0) {
            return "admin";
        } else {
            return "administrators";
        }
    }
}
  1. Create the script (for example with CRXDE Lite) and save it in the repository below /etc/workflow/scripts

  2. To specify a title that identifies the script in the Process Step edit dialog, add the following properties to the jcr:content node of your script:

    Name Type Value
    jcr:mixinTypes Name[] mix:title
    jcr:title String The name to appear in the edit dialog.
  3. Edit the Dynamic Participant Step instance and specify the script to be used. 

Handling Workflow Packages

Workflow packages can be passed to a workflow for processing. Workflow packages contain references to resources such as pages and assets.

Huomautus:

The following workflow process steps accept workflow packages for bulk page activation:

You can develop workflow steps that obtain the package resources and process them. The following members of the com.day.cq.workflow.collection package provide access to workflow packages:

  • ResourceCollection: Workflow package class.
  • ResourceCollectionUtil: Use to retrieve ResourceCollection objects.
  • ResourceCollectionManager: Creates and retrieves collections. An implementation is deployed as an OSGi service. 

The following example Java class demonstrates how to obtain package resources:

package com.adobe.example;

import java.util.ArrayList;
import java.util.List;

import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.collection.ResourceCollection;
import com.day.cq.workflow.collection.ResourceCollectionManager;
import com.day.cq.workflow.collection.ResourceCollectionUtil;
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.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import org.osgi.framework.Constants;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session; 

@Component
@Service
public class LaunchBulkActivate implements WorkflowProcess {
	
	private static final Logger log = LoggerFactory.getLogger(LaunchBulkActivate.class);

	@Property(value="Bulk Activate for Launches")
	 static final String PROCESS_NAME ="process.label";
	@Property(value="A sample workflow process step to support Launches bulk activation of pages")
	static final String SERVICE_DESCRIPTION = Constants.SERVICE_DESCRIPTION;
	
	@Reference
	private ResourceCollectionManager rcManager;
public void execute(WorkItem workItem, WorkflowSession workflowSession) throws Exception {
    Session session = workflowSession.getSession();
    WorkflowData data = workItem.getWorkflowData();
    String path = null;
    String type = data.getPayloadType();
    if (type.equals(TYPE_JCR_PATH) && data.getPayload() != null) {
        String payloadData = (String) data.getPayload();
        if (session.itemExists(payloadData)) {
            path = payloadData;
        }
    } else if (data.getPayload() != null && type.equals(TYPE_JCR_UUID)) {
        Node node = session.getNodeByUUID((String) data.getPayload());
        path = node.getPath();
    }

    // CUSTOMIZED CODE IF REQUIRED....

    if (path != null) {
        // check for resource collection
        ResourceCollection rcCollection = ResourceCollectionUtil.getResourceCollection((Node)session.getItem(path), rcManager);
        // get list of paths to replicate (no resource collection: size == 1
        // otherwise size >= 1
        List<String> paths = getPaths(path, rcCollection);
        for (String aPath: paths) {

            // CUSTOMIZED CODE....

        }
    } else {
        log.warn("Cannot process because path is null for this " + "workitem: " + workItem.toString());
    }
}

/**
 * helper
 */
private List<String> getPaths(String path, ResourceCollection rcCollection) {
    List<String> paths = new ArrayList<String>();
    if (rcCollection == null) {
        paths.add(path);
    } else {
        log.debug("ResourceCollection detected " + rcCollection.getPath());
        // this is a resource collection. the collection itself is not
        // replicated. only its members
        try {
            List<Node> members = rcCollection.list(new String[]{"cq:Page", "dam:Asset"});
            for (Node member: members) {
                String mPath = member.getPath();
                paths.add(mPath);
            }
        } catch(RepositoryException re) {
            log.error("Cannot build path list out of the resource collection " + rcCollection.getPath());
        }
    }
    return paths;
}
}

Example: Create a Logger Workflow Step

The following procedures create an example workflow step that sends workflow-related information to the AEM log. Generally, the quickest way to create a custom step component is to create a copy of the No Operation step component. The No Operation step component includes the nodes that define the edit dialog, process arguments, and parameters for using the process with forms. After copying the component you need to change several title and description properties that appear in the UI, and specify the class that implements the step behavior.

Creating the step component

Create a custom step component that enables model creators to set two process arguments. Copy the No Operation component to your application and modify node properties.

  1. Use CRXDE Lite to create a folder named mycompany below the /content/apps folder. Continue to create the folders of the following path:

    /content/apps/mycompany/components/workflow

  2. Copy the noopprocess at /libs/cq/workflow/components/workflow/noopprocess to the /apps/mycompany/components/workflow folder. Change the name of the node to loggerprocess.

  3. Change following properties of the /apps/mycompany/components/workflow/loggerprocess node:

    • jcr:title: Logger
    • jcr:description: Writes workflow information to the log file.

    These properties identify the component step in the Sidekick of the Models editor.

  4. Select the loggerprocess/cq:editConfig/cq:formParameters node and change the following property values:

    • jcr:title: Logger Process
    • jcr:description: Logs workflow values to the log.
    • PROCESScom.adobe.example.workflow.impl.process.LoggerProcess

    These properties identify the workflow component and implementation when using it with a form.

  5. Select the loggerprocess/dialog node and change the value of the title property to Logger Process - Step Properties.

    The dialog node defines the edit dialog of the component.

  6. Select the loggerprocess/dialog/items/tabs/items/processargs node and change the value of the path property to:

    /apps/mycompany/components/workflow/loggerprocess/processargs.infinity.json

    The widgets that are defined below the loggerprocess/processargs node appear in the dialog.

  7. To add argument widgets to the component, add two nodes of type cq:Widget below the /apps/mycompany/components/workflow/loggerprocess/processargs/items/arguments/items node. Use the following node names:

    • singlearg
    • multiarg
  8. Add the following properites to the singlearg node:

    Name Type Value
    xtype String textfield
    name String ./metaData/argSingle
    fieldLabel String Single Argument
  9. Add the following properites to the multiarg node:

    Name Type Value
    xtype String multifield
    name String ./metaData/argMulti
    fieldLabel String Multi Arg

The Logger Process component is added to the Sidekick of the Model editor.

The edit dialog of the Logger Process step component contains the widgets that the singlearg and multiarg nodes define:

screen_shot_2012-02-01at20808pm

Creating the step implementation

Create the com.adobe.example.workflow.impl.process.LoggerProcess implementation. This is the class that you specified for the PROCESS property of the loggerprocess/cq:editConfig/cq:formParameters node.

Huomautus:

Create a Maven project using the multimodule-content-package-archetype archetype. To install the content package, use the command:

mvn clean install -P autoInstallPackage

See Defining a Process Step with a Java Class for details about creating a Java based process step.

package com.adobe.example.workflow.impl.process;

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.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;

import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.Arrays;
 
/**
 * Sample workflow process that logs arguments into the logfile.
 */
@Component
@Service

public class LoggerProcess implements WorkflowProcess {
 
	@Property(value = "Logger process implementation.")
	static final String DESCRIPTION = Constants.SERVICE_DESCRIPTION; 
    @Property(value = "Adobe")
    static final String VENDOR = Constants.SERVICE_VENDOR;
    @Property(value = "Logger Process")
    static final String LABEL="process.label";
	
	
   private static final Logger log = LoggerFactory.getLogger(LoggerProcess.class);
 
    public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
        String singleValue = args.get("argSingle", "not set");
        String[] multiValue = args.get("argMulti", new String[]{"not set"});
 
        log.info("-- Workflow Paramter - Single Value: {}", singleValue);
        log.info("-- Workflow Paramter - Multi Value: {}", Arrays.toString(multiValue));
    }
}

LoggerProcess Maven Dependencies

When you create a Maven project using the multimodule-content-package-archetype archetype, to support the LoggerProcess class you need to add the following dependencies to the pom.xml files.

Varoitus:

The following is an example only, please check the versions required for your instance before using. You can do this using the Web Console; for example:

http://localhost:4502/system/console/depfinder

  • <dependency>
    	<groupId>com.adobe.granite</groupId>
    	<artifactId>com.adobe.granite.workflow.api</artifactId>
    	<version>1.0.0</version>
    	<scope>provided</scope>
    </dependency>
    <dependency>
    	<groupId>org.apache.sling</groupId>
    	<artifactId>org.apache.sling.jcr.jcr-wrapper</artifactId>
    	<version>2.0.0</version>
    	<scope>provided</scope>
    </dependency>
  • In addition, ensure that the dependency for the slf4j-api artifact is correct.


Lisensoitu Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License -lisenssin mukaan.  Creative Commons -lisenssien ehdot eivät koske Twitter™- ja Facebook-viestejä.

Lakisääteiset ilmoitukset   |   Online-tietosuojakäytäntö