Article summary

Summary

Discusses how to use the Workflow API to create a custom Dynamic Participant Step. This article uses DS Annotations to create the custom workflow step as opposed to Felix SRC annotations. 

A special thank you to Ratna Kumar Kotla, a member of the AEM community, for testing this article and ensuring it works. 

Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
Java, OSGi, Maven
Tested On  Adobe Experience Manager 6.4

Introduction

You can develop a custom Adobe Experience Manager (AEM) 6.4 Dynamic Participant workflow step. A Dynamic Participant Step component is similar to Participant Step except the participant to which the workflow item is assigned is determined at run time. You create a Dynamic Participant workflow step by implementing ParticipantStepChooser.

When creating a Dynamic Participant Step, you can use application logic to determine to whom the workflow item is assigned. For example, your participant chooser can select the user that has the fewest work items. This article walks you through how to create a custom Dynamic Participant Step and use it in an Experience Manager workflow. In this workflow example, content is reviewed and approved using a custom Dynamic Participant Step.

dialag
A Touch UI dialog used in a workflow step

Create an Experience Manager 13 archetype project

You can create an Experience Manager archetype project by using the Maven archetype plugin. In this example, assume that the working directory is C:\AdobeCQ. 

ProjectA
An Experience Manager Maven Archetype 13 project

To create an Experience Manager archetype project, perform these steps:

1. Open the command prompt and go to your working directory (for example, C:\AdobeCQ).

2. Run the following Maven command:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeGroupId=com.adobe.granite.archetypes -DarchetypeArtifactId=aem-project-archetype -DarchetypeVersion=13 -DarchetypeCatalog=https://repo.adobe.com/nexus/content/groups/public/

3. When prompted, specify the following information:

  • groupId - partstep64
  • artifactId - partstep64
  • version - 1.0-SNAPSHOT
  • package - com.aem.community.wf
  • appsFolderName - partstep64
  • artifactName - partstep64
  • componentGroupName - partstep64
  • contentFolderName - partstep64
  • cssId - partstep64
  • packageGroup - partstep64
  • siteName -partstep64

4. WHen prompted, specify Y.

5. Once done, you will see a message like:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:42 min
[INFO] Finished at: 2016-04-25T14:34:19-04:00
[INFO] Final Memory: 16M/463M
[INFO] ------------------------------------------------------------------------

6. Change the working directory to partstep64 and then enter the following command.

mvn eclipse:eclipse

After you run this command, you can import the project into Eclipse as discussed in the next section.

Note:

If you have not setup Maven, see this article Creating an Adobe Experience Manager 6.4 Project using Adobe Maven Archetype 13.

Add Java files to the Maven project using Eclipse 

To make it easier to work with the Maven generated project, import it into the Eclipse development environment, as shown in the following illustration.

project
Eclipse Import Project Dialog

Note:

Do not worry about the errors reported in Eclipse. It does not read the POM file where the APIs are resolved. You build the bundle with Maven. Eclipse is used to edit the Java files and the POM file.

The next step is to add a Java file to the com.aem.community.wf.core package. The Java class that you create in this section impements the com.adobe.granite.workflow.exec.ParticipantStepChooser interface.

Because the ParticipantStep class implements ParticipantStepChooser, you have to create a method named getParticipant. This method returns the dynamically resolved Principal id.

The following Java code represents the ParticipantStepImp class.

package com.aem.community.wf.core;

import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.HistoryItem;
import com.adobe.granite.workflow.exec.ParticipantStepChooser;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.Workflow;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import java.util.List;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



@Component(service=ParticipantStepChooser.class, property = {"chooser.label=Sample Implementation of dynamic participant chooser"})

public class ParticipantStep implements ParticipantStepChooser
{
	  private static final Logger logger = LoggerFactory.getLogger(ParticipantStep.class);
	   
	  public String getParticipant(WorkItem workItem, WorkflowSession wfSession, MetaDataMap metaDataMap)
	    throws WorkflowException
	  {
	    logger.info("################ Inside the SampleProcessStepChooserImpl GetParticipant ##########################");
	    String participant = "admin";
	    Workflow wf = workItem.getWorkflow();
	    List<HistoryItem> wfHistory = wfSession.getHistory(wf);
	    if (!wfHistory.isEmpty()) {
	      participant = "administrators";
	    } else {
	      participant = "admin";
	    }
	    logger.info("####### Participant : " + participant + " ##############");
	    return participant;
	  }
	}

Note:

Notice the value for chooser.label. This is the value that shows up the Dynamic Participant step (this is shown later in ths article.)

Modify the Maven POM file

Add the following POM dependency to the POM file located at C:\AdobeCQ\partstep64.

<dependency>
    <groupId>com.adobe.aem</groupId>
    <artifactId>uber-jar</artifactId>
    <version>6.4.0</version>
    <classifier>apis</classifier>
    <scope>provided</scope>
</dependency>
               
  <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-atinject_1.0_spec</artifactId>
       <version>1.0</version>
       <scope>provided</scope>
   </dependency>

When you add new Java classes under core, you need to modify a POM file to successfully build the OSGi bundle. You modify the POM file located at C:\AdobeCQ\partstep64\core. The following code represents this POM file.

<?xml version="1.0" encoding="UTF-8"?>
<!--
 |  Copyright 2017 Adobe Systems Incorporated
 |
 |  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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>partstep64</groupId>
        <artifactId>partstep64</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>partstep64.core</artifactId>
    <packaging>bundle</packaging>
    <name>partstep64 - Core</name>
    <description>Core bundle for partstep64</description>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.sling</groupId>
                <artifactId>maven-sling-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <!-- Import any version of javax.inject, to allow running on multiple versions of AEM -->
                        <Import-Package>javax.inject;version=0.0.0,*</Import-Package>
                        <Sling-Model-Packages>
                            com.aem.community.wf.core
                        </Sling-Model-Packages>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- OSGi Dependencies -->
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
      
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-atinject_1.0_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.cmpn</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.annotation</artifactId>
        </dependency>
        <!-- Other Dependencies -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.sling</groupId>
            <artifactId>org.apache.sling.models.api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
        </dependency>
        <dependency>
            <groupId>junit-addons</groupId>
            <artifactId>junit-addons</artifactId>
        </dependency>
    </dependencies>
</project>

Build the OSGi bundle using Maven

To build the OSGi bundle by using Maven, perform these steps:

  1. Open the command prompt and go to the C:\AdobeCQ\partstep64.
  2. Run the following maven command: mvn -PautoInstallPackage install.
  3. The OSGi component can be found in the following folder: C:\AdobeCQ\partstep64\core\target. The file name of the OSGi component is partstep64.core-1.0-SNAPSHOT.jar.

The command -PautoInstallPackage automatically deploys the OSGi bundle to AEM.

View the Active OSGi bundle

After you deploy the OSGi bundle, you can see it in the Apache Felix Web Console.

OSGi
OSGi bundle

View your OSGi bundle by performing these steps:

  1. Login to Adobe Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).
  2. Click the Bundles tab, sort the bundle list by Id, and note the Id of the last bundle.

Build a Touch UI dialog for the custom workflow step and ensure that the nodes resemble the following illustration. 

Create an AEM Workflow that uses the custom workflow step

In this step, create an AEM workflow in the Touch UI environment that deletes content and uses the custom step to log messages. 

 

Model
An AEM Workflow that uses the custom Participant step

To create a workflow that uses the custom participant step, perform the following tasks:

1. Click the Hammer icon in the main AEM view at http://localhost:4502. 

2. Click Workflow on the side menu. 

3. Click Models. 

4. Click the Create button then Create Model

5. Enter ViewPageDetails as the workflow title.

6. Open the workflow by selecting it and clicking Edit. 

7. Add the Dynamic Participant Step component from the side rail onto the workflow model. Make this the second step of the workflow.

 

Model1
Add the Dynamic Participant step

8. Double click on this step.  Select the Sample Implementation of dynamic participant chooser value from the drop donw as shown in this illustration. 

 

Model2
Select the value that corresponds to the chooser.label in the Java class

9. Click the Sync button.

Invoke the Workflow

The final task to perform is to invoke the workflow from the Experience Manager Touch UI at:

http://localhost:4502/sites.html/content

Select an AEM page and from the top menu, select Create, Workflow as shown in this illustration.  

WF2
Invoke an AEM Workflow

The Workflow dialog appears. Select the workflow, as shown in this illustration.  

viewPage
Select a workflow

Click the Next button and then the Create button. This invokes the workflow. You will see a success message if the workflow is successful. 

Open the site admin UI at: 

http://localhost:4502/sites.html/content/we-retail

click on the messages icon, as shown here. 

wf4
The admin message generated by the first step in the workflow

This bring you to the Workflow confirmation view. Click the Complete button and then the OK button.

Model4
Click the Complete button to complete the workflow

When the administrator (the user whom the workflow assigns the step) clicks the Complete button. The step logs this information to the log file

17.10.2018 14:08:34.887 *INFO* [0:0:0:0:0:0:0:1 [1539799714881] POST /bin/workflow/inbox HTTP/1.1] com.aem.community.wf.core.ParticipantStep ################ Inside the SampleProcessStepChooserImpl GetParticipant ##########################


17.10.2018 14:08:34.887 *INFO* [0:0:0:0:0:0:0:1 [1539799714881] POST /bin/workflow/inbox HTTP/1.1] com.aem.community.wf.core.ParticipantStep ####### Participant : administrators ##############




See also

Congratulations, you have just created a custom Dynamic Participant step. Please refer to the Experience League page for more articles that discuss how to build AEM services/applications.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy