Article summary

Summary
Discusses how to programmatically invoke an Adobe Experience Manager workflow using the AEM Java Workflow API.    
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
Java, OSGi Maven, HTML
Version(s) Adobe Experience Manager 5.5, 5.6, 6.x

Note:

For more information about Adobe Experience Manager Workflows, watch this session of Ask the AEM Community Experts: AEM Workflows .

Introduction

You can create a workflow for Adobe Experience Manager (AEM) and then programmatically invoke the workflow by using AEM Workflow API. A workflow automates Experience Manager activities and is a series of steps that are executed in a specific order. Each step performs a distinct activity such as activating a page or sending an email message. Workflows can interact with assets in the repository, user accounts, and Experience Manager services. Therefore, workflows can coordinate complicated activities that involve any aspect of Experience Manager.

intro
The AEM workflow user interface

This article creates a basic workflow that deletes a specific node and then discusses how to invoke the workflow using the AEM Workflow API. The AEM Workflow API is located in the com.day.cq.workflow package. The Java code that invokes an AEM workflow is implemented as an OSGi bundle. For information about this Java API, see Package com.day.cq.workflow.model.

Create an Experience Manager application folder structure 

Create an application folder structure that contains templates, components, and pages by using CRXDE Lite.

CQAppSetup
An Experience Manager application folder structure

The following describes each application folder:

  • application name: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on.
  • components: contains components that your application uses.
  • page: contains page components. A page component is a script such as a JSP file.
  • global: contains global components that your application uses.
  • template: contains templates on which you base page components.
  • src: contains source code that comprises an OSGi component (this development article does not create an OSGi bundle using this folder).
  • install: contains a compiled OSGi bundles container.

To create an application folder structure:

1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click the apps folder (or the parent folder), select Create, Create Folder.

4. Enter the folder name into the Create Folder dialog box. Enter invokeworkflow

5. Repeat steps 1-4 for each folder specified in the previous illustration. 

6. Click the Save All button.

 

Note:

You have to click the Save All button when working in CRXDELite for the changes to be made.  

Create a template 

You can create a template by using CRXDE Lite. An Experience Manager template enables you to define a consistent style for the pages in your application. A template comprises of nodes that specify the page structure. For more information about templates, see Templates.

To create a template, perform these tasks:

1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.
2. Select CRXDE Lite.
3. Right-click the template folder (within your application), select Create, Create
Template.
4. Enter the following information into the Create Template dialog box:

  • Label: The name of the template to create. Enter templateWorkflow
  • Title: The title that is assigned to the template.
  • Description: The description that is assigned to the template.
  • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter invokeworkflow/components/page/templateWorkflow.
  • Ranking: The order (ascending) in which this template will appear in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.

5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.
6. Click Next for Allowed Parents.
7. Select OK on Allowed Children.

Create a render component that uses the template 

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as an Experience Manager developer to create scripts that perform specific functionality. For more information about components, see Components.

By default, a component has at least one default script, identical to the name of the component. To create a render component, perform these tasks:

1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.
2. Select CRXDE Lite.
3. Right-click /apps/invokeworkflow/components/page, then select
Create, Create Component.
4. Enter the following information into the Create Component dialog box:

  • Label: The name of the component to create. Enter templateWorkflow.
  • Title: The title that is assigned to the component.
  • Description: The description that is assigned to the template.
  • Super Type: foundation/components/page

5. Select Next for Advanced Component Settings and Allowed Parents.
6. Select OK on Allowed Children.
7. Open the templateJCR.jsp located at: /apps/invokeworkflow/components/page/templateWorkflow/templateWorkflow.jsp.
8. Enter the following JSP code.

 

<html>
<head>
<title>Hello World !!!</title>
</head>
<body>
<h1>Programmatically Invoke an AEM workflow!!</h1>
<h2>This page will programmatically invoke an AEM workflow</h2>
</body>
</html>

Setup Maven in your development environment 

You can use Maven to build an OSGi bundle that uses the Java Excel API and the JCR API. Maven manages required JAR files that a Java project needs in its class path. Instead of searching the Internet trying to find and download third-party JAR files to include in your project’s class path, Maven manages these dependencies for you.

You can download Maven 3 from the following URL:

http://maven.apache.org/download.html

After you download and extract Maven, create an environment variable named M3_HOME. Assign the Maven install location to this environment variable. For example:

C:\Programs\Apache\apache-maven-3.0.4

Set up a system environment variable to reference Maven. To test whether you properly setup Maven, enter the following Maven command into a command prompt:

%M3_HOME%\bin\mvn -version

This command provides Maven and Java install details and resembles the following message:

Java home: C:\Programs\Java64-6\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

 

Note:

For more information about setting up Maven and the Home variable, see: Maven in 5 Minutes.

Next, copy the Maven configuration file named settings.xml from [install location]\apache-maven-3.0.4\conf\ to your user profile. For example, C:\Users\scottm\.m2\.

You have to configure your settings.xml file to use Adobe’s public repository. For information, see Adobe Public Maven Repository at http://repo.adobe.com/.

Create an Experience Manager 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.  

plugin1


To create an 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 archetype:generate -DarchetypeGroupId=com.day.jcr.vault -DarchetypeArtifactId=multimodule-content-package-archetype -DarchetypeVersion=1.0.0 -DarchetypeRepository=adobe-public-releases

3. When prompted for additional information, specify these values:

  • groupId: com.aem.sample.workflow
  • artifactId: InvokeWorkflow
  • version: 1.0-SNAPSHOT
  • package: com.aem.sample.workflow
  • appsFolderName: customer-training
  • artifactName: Customer Training Package
  • packageGroup: adobe training
  • confirm: Y

4. Once done, you will see a message like:
[INFO] Finished at: Wed Mar 27 13:38:58 EDT 2013
[INFO] Final Memory: 10M/184M

5. Change the command prompt to the generated project. For example: C:\AdobeCQ\InvokeWorkflow. Run the following Maven command: mvn eclipse:eclipse.

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

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.
 

WorkflowInvoke

 

The next step is to add Java files to the com.aem.sample.workflow package. The Java file that you create in this section uses the AEM Java Workflow API. The AEM Workflow API lets you programmatically invoke an AEM workflow. For information about this Java API, see Package com.day.cq.workflow.model.

 

 

InvokeAEMWorkflow interface

Create a Java Inteface named InvokeAEMWorkflow located in the com.aem.sample.workflow package. This interface contains a single method named StartWorkflow that accepts two parameters:

  • workflowName: A string that represents an AEM workflow. This value is represented as a node. For example. assume you have a workflow named testworkflow. In this situation, this parameter value is /etc/workflow/models/deletecontent/jcr:content/model.
  • workflowContent: A string value that represents the AEM content on which the workflow modifies. For example, assume you want to perform a workflow on a web page named sling5. An example value for this parameter is /content/sling5.
package com.aem.sample.workflow;

public interface InvokeAEMWorkflow {
	
	public String StartWorkflow(String workflowName, String workflowContent); 

}

InvokeAEMWorkflowImp class 

Create a Java class named InvokeAEMWorkflowImp located in the com.aem.sample.workflow package that extends InvokeAEMWorkflow. Within the StartWorkflow method, create a WorkflowSession instance. You use this object to programmatically invoke an AEM workflow as shown in the following code example.

//Create a workflow session 
WorkflowSession wfSession = workflowService.getWorkflowSession(session);
        	
// Get the workflow model
WorkflowModel wfModel = wfSession.getModel(workflowName); 
            
// Get the workflow data
// The first param in the newWorkflowData method is the payloadType.  Just a fancy name to let it know what type of workflow it is working with.
WorkflowData wfData = wfSession.newWorkflowData("JCR_PATH", workflowContent);
            
// Invoke the Workflow
wfSession.startWorkflow(wfModel, wfData);
            
  

The following Java code represents the entire INvokeAEMWorkflowImp class.  

package com.aem.sample.workflow;
 
import java.util.Calendar; 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
   
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.io.InputStream;
   
import javax.jcr.Repository; 
import javax.jcr.SimpleCredentials; 
import javax.jcr.Node; 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
    
import org.apache.jackrabbit.commons.JcrUtils;
   
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
   
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.jcr.api.SlingRepository;
   
import javax.jcr.Session;
import javax.jcr.Node; 
 
//Adobe CQ Workflow APIs
import com.day.cq.workflow.model.WorkflowModel ; 
import com.day.cq.workflow.WorkflowService ; 
import com.day.cq.workflow.WorkflowSession; 
import com.day.cq.workflow.exec.WorkflowData; 

//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory ; 
import org.apache.sling.api.resource.ResourceResolver; 
import org.apache.sling.api.resource.Resource; 

 
//This is a component so it can provide or consume services
@Component
   
@Service
public class InvokeAEMWorkflowImp implements InvokeAEMWorkflow {
     
    @Reference
    private WorkflowService workflowService;
 
    private Session session;
     
    @Reference
    private ResourceResolverFactory resolverFactory;
          
   
     
@Override
public String StartWorkflow(String workflowName, String workflowContent) {
                 
try
{
	//Invoke the adaptTo method to create a Session 
    ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
    session = resourceResolver.adaptTo(Session.class);
    
 //Create a workflow session 
  WorkflowSession wfSession = workflowService.getWorkflowSession(session);
             
 // Get the workflow model
 WorkflowModel wfModel = wfSession.getModel(workflowName); 
             
  // Get the workflow data
  // The first param in the newWorkflowData method is the payloadType.  Just a fancy name to let it know what type of workflow it is working with.
 WorkflowData wfData = wfSession.newWorkflowData("JCR_PATH", workflowContent);
             
   // Run the Workflow.
    wfSession.startWorkflow(wfModel, wfData);
             
   return workflowName +" has been successfully invoked on this content: "+workflowContent ; 
    }
catch(Exception e)
{
    e.printStackTrace();
}
         
return null;
 }
}

Modify the Maven POM file

Modify the POM files to successfully build the OSGi bundle. In the POM file located at C:\AdobeCQ\InvokeWorkflow\bundle, add the following dependencies.

  • org.apache.felix.scr
  • org.apache.felix.scr.annotations
  • com.day.cq.workflow

Because the AEM Workflow API is used, a Maven dependency on the repository that contains the Workflow API exists. Add the following element to your POM file.

 

<repositories>
    <repository>
        <id>adobe</id>
        <name>Adobe Public Repository</name>
        <url>http://repo.adobe.com/nexus/content/groups/public/</url>
        <layout>default</layout>
    </repository>
    </repositories>
        <pluginRepositories>
        <pluginRepository>
        <id>adobe</id>
        <name>Adobe Public Repository</name>
        <url>http://repo.adobe.com/nexus/content/groups/public/</url>
        <layout>default</layout>
    </pluginRepository>
</pluginRepositories>

Once you add this repository element to your POM file, you can add the following dependency to your POM file that lets you use the Workflow API in your Java code.

<dependency>
        <groupId>com.day.cq.workflow</groupId>
        <artifactId>cq-workflow-api</artifactId>
        <version>5.5.0</version>
        <scope>provided</scope>
</dependency>

The following XML represents the POM file to build the OSGi bundle that contains the Workflow API.  

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd ">
    <modelVersion>4.0.0</modelVersion>
    <!-- ====================================================================== -->
    <!-- P A R E N T P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->
    <parent>
        <groupId>com.aem.sample.workflow</groupId>
        <artifactId>InvokeWorkflow</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- ====================================================================== -->
    <!-- P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->

    <artifactId>InvokeWorkflow-bundle</artifactId>
    <packaging>bundle</packaging>
    <name>Customer Training Bundle</name>

    <!-- ====================================================================== -->
    <!-- B U I L D D E F I N I T I O N -->
    <!-- ====================================================================== -->
    <build>

        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-scr-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-scr-descriptor</id>
                        <goals>
                            <goal>scr</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>com.aem.sample.workflow.InvokeWorkflow-bundle</Bundle-SymbolicName>
                    </instructions>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.sling</groupId>
                <artifactId>maven-sling-plugin</artifactId>
                <configuration>
                    <slingUrl>http://${crx.host}:${crx.port}/apps/customer-training/install</slingUrl>
                    <usePut>true</usePut>
                </configuration>
            </plugin>
        </plugins>
    </build>

       <dependencies>
      
      <dependency>
            <groupId>org.apache.sling</groupId>
            <artifactId>org.apache.sling.api</artifactId>
            <version>2.2.4</version>
            <scope>provided</scope>
        </dependency>
      
      <dependency>
            <groupId>com.day.cq.workflow</groupId>
            <artifactId>cq-workflow-api</artifactId>
            <version>5.5.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.scr.annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
          
        <dependency>
         <groupId>org.apache.felix</groupId>
   
         <artifactId>org.osgi.core</artifactId>
   
         <version>1.4.0</version>
      </dependency>
         
        
          
    <dependency>
    <groupId>org.apache.jackrabbit</groupId>
    <artifactId>jackrabbit-core</artifactId>
    <version>2.4.3</version>
    </dependency>
       
    <dependency>
    <groupId>org.apache.jackrabbit</groupId>
    <artifactId>jackrabbit-jcr-commons</artifactId>
    <version>2.4.3</version>
    </dependency>
   
    <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.jcr.api</artifactId>
        <version>2.0.4</version>
      </dependency>
         
      <dependency>
         <groupId>javax.jcr</groupId>
         <artifactId>jcr</artifactId>
         <version>2.0</version>
      </dependency>
       
               
    </dependencies>
     
    <repositories>
        <repository>
            <id>adobe</id>
            <name>Adobe Public Repository</name>
            <url>http://repo.adobe.com/nexus/content/groups/public/</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>adobe</id>
            <name>Adobe Public Repository</name>
            <url>http://repo.adobe.com/nexus/content/groups/public/</url>
            <layout>default</layout>
        </pluginRepository>
    </pluginRepositories>       
</project>

Build the OSGi bundle using Maven

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

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

 

Deploy the OSGi bundle that contains Workflow application logic  

Once you deploy the OSGi bundle, you are able to invoke the StartWorkflow method defined in the InvokeAEMWorkflowImp class (this is shown later in this development article). After you deploy the OSGi bundle, you will be able to see it in the Apache Felix Web Console.  

OSG

Deploy the OSGi bundle by performing these steps:

  1. Login to 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.
  3. Click the Install/Update button.
  4. Browse to the bundle JAR file you just built using Maven. (C:\AdobeCQ\InvokeWorkflow\bundle\target).
  5. Click Install.
  6. Click the Refresh Packages button.
  7. Check the bundle with the highest Id.
  8. Click Active. Your new bundle should now be listed with the status Active.
  9. If the status is not Active, check the CQ error.log for exceptions.

Create an AEM Workflow that deletes content

In this step, create an AEM workflow that deletes content.

Workflow

You can create an Experience Manager workflow that deletes content and is invoked by the OSGi bundle that you created. To create a workflow, you use the Workflow console located at the following URL:

http://localhost:4502/cf#/libs/cq/workflow/content/console.html

To create a workflow that deletes content (and invoked in this development article using the Workflow API), perform the following tasks:

1. Log into the Workflow console.

2. Click the New button.

3. Enter DeleteContent as the workflow title.

4. Open the DeleteContent workflow by double-clicking on the name located in the grid view.The DeleteContent workflow model has a Start, Step 1, and an End.

5. Edit Step 1 by double-clicking on the step. Enter the following property values

  • Description - Administrator determines if content is deleted
  • Title - Administrator;
  • User/Group = admin

6. Add a Process step to the workflow by dragging-and-dropping the Delete Node component from the sidekick onto the workflow model. Make this the second step of the workflow as shown in the previous illustration.  

7. Click Save.

 

Note:

The DeleteContent workflow will be invoked by using the OSGi bundle that was created.  

Modify the templateWorkflow JSP to invoke the DeleteContent workflow  

Modify the templateWorkflow.jsp file to invoke the StartWorkflow method that is defined by the InvokeAEMWorkflowImp class. The first argument is the name of the workflow to invoke. Specify this value: /etc/workflow/models/deletecontent/jcr:content/model. The second argument is the content on which to base the workflow. Specify /content/sling5 (this page will be created later in the article)

To invoke this service, you call sling.getService method as shown in the following example.

//create a InvokeAEMWorkflow instance
com.aem.sample.workflow.InvokeAEMWorkflow wfService = sling.getService(com.aem.sample.workflow.InvokeAEMWorkflow.class);

The following code represents the templateWorkflow JSP page.  

<%@include file="/libs/foundation/global.jsp"%>
<%@taglib prefix="cq" uri="http://www.day.com/taglibs/cq/1.0" %>
<h1>TemplatePDF Page</h1>
<%
//create a InvokeAEMWorkflow instance
com.aem.sample.workflow.InvokeAEMWorkflow wfService = sling.getService(com.aem.sample.workflow.InvokeAEMWorkflow.class);

%>
<h2>About to invoke an AEM workflow using the AEM workflow APIs</h2>
 
<h3>AEM Workflow status: <%=  wfService.StartWorkflow("/etc/workflow/models/deletecontent/jcr:content/model","/content/sling5")%></h3>

Note:

Make sure that you reference the workflow model name. You can check the workflow model name in this JCR path: /etc/workflow/models/<name of your workflow model>.

 

Modify the templateWorkflow JSP file:

1. To view the CQ welcome page, enter the URL: http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Double-click /apps/invokeworkflow/components/page/templateWorkflow/templateWorkflow.jsp.

4. Replace the JSP code with the new code shown in this section.

5. Click Save All.

 

Create a CQ web page that lets users invokes the workflow

The final task is to create a site that contains a page that is based on the templateWorkflow (the template created earlier in this development article). This web page invokes the deletecontent workflow as shown in the following illustration.

page


When this page invokes the deletecontent workflow, an email is sent to the administrator (the first step of the worflow).

email


When the administrator clicks the Complete button in the menu, the Complete Work Item dialog is shown that specifies the Delete Node step (the second step in the workflow).

end

When the administrator clicks OK, the piece of content that is specified as the second argument (/content/sling5) is deleted and the workflow completes.

Create a CQ web page that is based on the templateWorkflow template.

1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.
Select Websites.

2. From the left hand pane, select Websites.

3. Select New Page.

4. Specify the title of the page in the Title field.

5. Specify the name of the page in the Name field.

6. Select templateWorkflow from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information, the template will not show up in the New Page dialog box.

6. Open the new page that you created by double-clicking it in the right pane. The new page opens in a web browser.

 

Note:

When running this example, make sure that you create an AEM web page named sling5 at the root of content. Follow the same process as above; however, name the web page sling5. After you invoke and complete the process, notice that the sling5 web page is deleted by the workflow.

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