Chapter 15. Integrating Business Processes and Workflows

Table of Contents
15.1. BPMN 2.0 and the Activiti Tools
15.2. Setting Up Activiti Integration With OpenIDM
15.3. Managing Workflows Over the REST Interface
15.4. Example Activiti Workflows With OpenIDM

Key to any identity management solution is the ability to provide workflow-driven provisioning activities, whether for self-service actions such as requests for entitlements, roles or resources, running sunrise or sunset processes, handling approvals with escalations, or performing maintenance.

OpenIDM provides an embedded workflow and business process engine based on Activiti and the Business Process Model and Notation (BPMN) 2.0 standard.

More information about Activiti and the Activiti project can be found at http://www.activiti.org.

15.1. BPMN 2.0 and the Activiti Tools

Business Process Model and Notation 2.0 is the result of consensus among Business Process Management (BPM) system vendors. The Object Management Group (OMG) has developed and maintained the BPMN standard since 2004.

The first version of the BPMN specification focused only on graphical notation, and quickly became popular with the business analyst audience. BPMN 1.x defines how constructs such as human tasks, executable scripts, and automated decisions are visualized in a vendor-neutral, standard way. The second version of BPMN extends that focus to include execution semantics, and a common exchange format. Thus, BPMN 2.0 process definition models can be exchanged not only between different graphical editors, but can also be executed as is on any BPMN 2.0-compliant engine, such as the engine embedded in OpenIDM.

Using BPMN 2.0, you can add artifacts describing workflow and business process behavior to OpenIDM for provisioning and other purposes. For example, you can craft the actual artifacts defining business processes and workflow in a text editor, or using a special Eclipse plugin. The Eclipse plugin provides visual design capabilities, simplifying packaging and deployment of the artifact to OpenIDM. See the Activiti BPMN 2.0 Eclipse Plugin documentation for instructions on installing Activiti Eclipse BPMN 2.0 Designer.

Also, read the Activiti User Guide section covering BPMN 2.0 Constructs, which describes in detail the graphical notations and XML representations for events, flows, gateways, tasks, and process constructs.

15.2. Setting Up Activiti Integration With OpenIDM

There are two modes of integrating Activiti with OpenIDM:

  • Local integration, where an embedded Activiti Process Engine is started in the OpenIDM OSGi container.

  • Remote integration, where OpenIDM and Activiti run as separate instances and the integration is done using a REST API.

15.2.1. Setting Up Local Integration

The embedded workflow and business process engine is provided as part of the standard OpenIDM build.

Install the OpenIDM build, as described in the Installation Guide. Start OpenIDM, and run the scr list command at the console to check that the workflow bundle is active.

-> scr list
...
[  14] [active       ] org.forgerock.openidm.workflow
...

To verify the workflow integration you need at least one workflow definition in the /path/to/openidm/workflow directory. A sample workflow (example.bpmn20.xml) is provided in the /path/to/openidm/samples/misc directory. Copy this workflow to the /path/to/openidm/workflow directory to test the workflow integration.

$ cd /path/to/openidm
$ cp samples/misc/example.bpmn20.xml workflow/

You can verify the workflow integration by using the REST API. The following REST call lists the defined workflows:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET
 "http://localhost:8080/openidm/workflow/processdefinition?_queryId=query-all-ids"
  

The sample workflow definition that you copied in the previous step is named osgiProcess. The result of the preceding REST call is therefore something like:

{"result":[
     {"_id":"osgiProcess:1:3",
      "name":"Osgi process"
     }
        ]
}
  

The osgiProcess definition calls OpenIDM, queries the available workflow definitions from Activiti, then prints the list of workflow definitions to the OpenIDM logs. Invoke the osgiProcess workflow with the following REST call to OpenIDM:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
 --data '{"_key":"osgiProcess"}'
  

The workflow prints the list of workflow definitions to the OpenIDM console. With the default sample, you should see something like this on the console:

script task using resolver: [
  result:[
    [_id:osgiProcess:1:3, name:Osgi process]
  ]
]
script task using expression resolver: [
  result:[
    [_id:osgiProcess:1:3, name:Osgi process]
  ]
]
  

15.2.2. Setting Up Remote Integration

You can set up integration with a remote Activiti engine, as described in the following steps.

  1. Download and install OpenIDM, as described in the Installation Guide.

  2. Download and unzip the Activiti zip file (activiti-5.10.zip) from Activiti Downloads page.

  3. Edit the Activiti configuration file to avoid a port conflict with OpenIDM. OpenIDM runs on port 8080 by default. Edit the file so that Activiti Explorer runs on port 9090 (by replacing each instance of 8080 with 9090). The following example uses sed on a UNIX system to replace all instances of 8080 with 9090.

    $ cd /path/to/activiti/setup/
    $ sed -i.bak 's/8080/9090/g' build.xml
        

    Note

    There is currently a bug in the Activiti demo which might mean that all port replacements are not made. If you cannot access Activiti Explorer (in the next step) after making this change, also edit the following file to find and replace each instance of 8080 with 9090: /path/to/activiti/apps/apache-tomcat-6.0.32/conf/server.xml.

  4. Set up the default Activiti demo.

    $ cd /path/to/activiti/setup/
    $ ant demo.start
        
  5. In a browser, check that Activiti Explorer is running (on localhost:9090/activiti-explorer). Log in with the default userid kermit and password kermit. If all is well, log out.

  6. Configure Tomcat to operate with OpenIDM.

    1. Stop Tomcat.

      $ cd /path/to/activiti/setup/
      $ ant tomcat.stop 
            
    2. Copy the OpenIDM remote workflow WAR file to the Tomcat webapps folder.

      $ cd /path/to/openidm/bin/workflow
      $ cp openidm-workflow-remote-.war \
       /path/to/activiti/apps/apache-tomcat-6.0.32/webapps/
            
    3. Copy the OpenIDM workflow Activiti demo jar file to the Tomcat Activiti Explorer library.

      $ cd /path/to/openidm/bin/workflow/
      $ cp openidm-workflow-activiti--jar-with-dependencies.jar \
       /path/to/activiti/apps/apache-tomcat-6.0.32/webapps/activiti-explorer/WEB-INF/lib/
            
    4. Edit the Activiti Explorer configuration file to be able to use the OpenIDM extensions.

      $ cd /path/to/activiti/
      $ vi apps/apache-tomcat-6.0.32/webapps/activiti-explorer/WEB-INF/applicationContext.xml
            

      Replace the processEngineConfiguration with the OpenIDM extended configuration. So remove this section:

             <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
              <property name="dataSource" ref="dataSource" />
              <property name="transactionManager" ref="transactionManager" />
              <property name="databaseSchemaUpdate" value="true" />
              <property name="jobExecutorActivate" value="true" />
              <property name="customFormTypes">
               <list>
                <ref bean="userFormType"/>
               </list>
              </property>
             </bean>
            

      and replace it with this section:

            <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
             <property name="dataSource" ref="dataSource" />
             <property name="transactionManager" ref="transactionManager" />
             <property name="databaseSchemaUpdate" value="true" />
             <property name="jobExecutorActivate" value="true" />
             <property name="customFormTypes">
               <list>
                <ref bean="userFormType"/>
               </list>
              </property>
            <property name="customSessionFactories">
              <list>
                <bean class="org.forgerock.openidm.workflow.activiti.impl.session.OpenIDMSessionFactory">
                  <property name="url" value="http://localhost:8080/openidm/"/>
                  <property name="user" value="openidm-admin"/>
                  <property name="password" value="openidm-admin"/>
                </bean>
              </list>
            </property>
            <property name="resolverFactories">
              <list>
                <bean class="org.forgerock.openidm.workflow.activiti.impl.OpenIDMResolverFactory"></bean>
                <bean class="org.activiti.engine.impl.scripting.VariableScopeResolverFactory"></bean>
                <bean class="org.activiti.engine.impl.scripting.BeansResolverFactory"></bean>
              </list>
            </property>
            <property name="expressionManager">
              <bean class="org.forgerock.openidm.workflow.activiti.impl.OpenIDMExpressionManager"> </bean>
            </property>
           </bean>
            
    5. Restart Tomcat.

      $ cd /path/to/activiti/setup/
      $ ant tomcat.start 
           
    6. Check that Activiti Explorer is running on localhost:9090/activiti-explorer, as you did in the previous section.

  7. Configure OpenIDM to use the remote Activiti engine instead of the local, bundled Activiti engine.

    1. Copy the workflow.json configuration file to the OpenIDM configuration directory.

      $ cd /path/to/openidm/
      $ cp samples/misc/workflow.json conf/
            
    2. Edit the workflow configuration file to specify the remote Activiti engine.

      $ vi conf/workflow.json
            

      Ensure that the url, username, and password fields contain the values that correspond to your remote Activiti engine.

      {
         "enabled" : true,
         "location" : "remote",
         "engine" : {
             "url" : "http://localhost:9090/openidm-workflow-remote-2.1.0/",
             "username" : "youractivitiuser",
             "password" : "youractivitipassword"
         }
      }
            
  8. Start up OpenIDM.

    $ cd /path/to/openidm/
    $ ./startup.sh
       
  9. Test the integration by sending the following CURL request to list the available workflows:

    $ curl
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request GET 
     "http://localhost:8080/openidm/workflow/processdefinition?_queryId=query-all-ids"
        
  10. Log in to the Activiti Explorer of the remote Activiti engine (with the default username (kermit) and password (kermit).

  11. Install the sample workflow (example.bpmn20.xml).

    1. In Activiti Explorer, click Manage.

    2. From the Deployments menu, select Upload New.

    3. Navigate to the sample workflow (/path/to/openidm/samples /misc/example.bpmn20.xml)

  12. Verify the integration by sending the following CURL request:

    $ curl
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request POST
     "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
     --data '{"_key":"osgiProcess"}'
        

    The request should return a process ID, similar to the following:

    {
      "_id":"614",
      "processInstanceId":"614",
      "status":"ended",
      "businessKey":null,
      "processDefinitionId":"osgiProcess:7:603"
    }
        

    This request starts the osgiProcess and writes the list of installed workflows to the Tomcat server log file (/path/to/activiti/apps/ apache-tomcat-6.0.32/logs/catalina.out).

  13. Test the integration with Activiti Explorer.

    1. Click Processes and select Osgi Process from the list of process definitions.

    2. Click Start Process.

    3. Check the output in the Tomcat server log file ( /path/to/activiti/apps/apache-tomcat-6.0.32/logs/catalina.out. The list of installed workflows is written to the log file.

15.2.3. Configuring the Activiti Engine

Whether you use the embedded Activiti engine, or a remote Activiti engine, you configure the OpenIDM Activiti module in a file named /path/to/openidm/conf/workflow.json. If this file is absent from the configuration, the workflow module is unavailable for use. In the default OpenIDM installation, the workflow.json file assumes an embedded Activiti engine, and has the following configuration:

{
   "enabled"  : "true"
}
  

You can disable the workflow module by setting the "enabled" property in this file to "false".

A sample workflow.json file, with all configurable properties, is provided in /path/to/openidm/samples/misc. To configure an Activiti engine beyond the default configuration that is provided, edit this file as required and copy it to the /path/to/openidm/conf directory.

The sample workflow.json file contains the following configuration:

  {
    "enabled"  : "true",
    "location" : "remote",
    "engine" : {
        "url" : "http://localhost:9090/openidm-workflow-remote-",
        "username" : "youractivitiuser",
        "password" : "youractivitipassword"
    },
    "mail" : {
        "host" : "yourserver.smtp.com",
        "port" : 587,
        "username" : "yourusername",
        "password" : "yourpassword",
        "starttls" : true
    },
    "history" : "audit"
}
  

These fields have the following meaning:

  • enabled. Indicates whether the Activiti module is enabled for use. Possible values are true or false. The default value is true.

  • location. Indicates whether the Activiti engine is embedded with OpenIDM, or remote. Possible values are embedded or remote. If remote, you must provide details for the engine property, below.

  • engine. Specifies the details of the remote Activiti engine. The following fields must be defined:

    • url. The URL of the remote engine, including the host name and port number.

    • username. A user name for the remote Activiti engine.

    • password. The password for the user specified above.

  • mail. Specifies the details of the mail server that Activiti will use to send email notifications. By default, Activiti uses the mail server localhost:25. To specify a different mail server, enter the details of the mail server here.

    • host. The host of the mail server.

    • port. The port number of the mail server.

    • username. The user name of the account that connects to the mail server.

    • password. The password for the user specified above.

    • startTLS. Whether startTLS should be used to secure the connection.

  • history. Determines the history level that should be used for the Activiti engine. For more information, see Configuring the Activiti History Level.

15.2.3.1. Configuring the Activiti History Level

The Activiti history level determines how much historical information is retained when workflows are executed. You can configure the history level by setting the history property in the workflow.json file, for example:

"history" : "audit"

The following history levels can be configured:

  • none. No history archiving is done. This level results in the best performance for workflow execution, but no historical information is available.

  • activity. Archives all process instances and activity instances. No details are archived.

  • audit. This is the default level. All process instances, activity instances and submitted form properties are archived so that all user interaction through forms is traceable and can be audited.

  • full. This is the highest level of history archiving and has the greatest performance impact. This history level stores all information as in the audit level as well as any process variable updates.

15.2.4. Defining Activiti Workflows

The following section outlines the process to follow when you create an Activiti workflow for OpenIDM. Before you start creating workflows, you must configure the Activiti engine, as described in Configuring the Activiti Engine.

  1. Define your workflow in a text file, either using an editor, such as Activiti Eclipse BPMN 2.0 Designer, or a simple text editor.

  2. Package the workflow definition file as a .bar file (Business Archive File). If you are using Eclipse to define the workflow, a .bar file is created when you select "Create deployment artifacts". Essentially, a .bar file is the same as a .zip file, but with the .bar extension.

  3. Copy the .bar file to the openidm/workflow directory.

  4. Invoke the workflow using a script (in openidm/script/) or directly using the REST interface. For more information, see Invoking Activiti Workflows.

  5. You can also schedule the workflow to be invoked repeatedly, or at a future time. For more information, see the Scheduler Reference

15.2.5. Invoking Activiti Workflows

You can invoke workflows and business processes from any trigger point within OpenIDM, including reacting to situations discovered during reconciliation. Workflows can be invoked from script files, using the openidm.action() function, or directly from the REST interface.

The following sample script extract shows how to invoke a workflow from a script file:

/*
 * Calling 'myWorkflow' workflow
 */

var params = {
 "foo" : "bar",
 "_key": "myWorkflow"
};

openidm.action('workflow/processinstance', {"_action" : "createProcessInstance"}, params);

You can invoke the same workflow from the REST interface by sending the following REST call to OpenIDM:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
 --data '{"_key":"myWorkflow", "foo":"bar"}'
  

There are two ways in which you can specify the workflow definition that is used when a new workflow instance is started.

  • _key specifies the id attribute of the workflow process definition, for example:

    <process id="sendNotificationProcess" name="Send Notification Process">
          

    If there is more than more than one workflow definition with the same _key parameter, the latest deployed version of the workflow definition is invoked.

  • _processDefinitionId specifies the ID that is generated by the Activiti Process Engine when a workflow definition is deployed, for example:

    "sendNotificationProcess:1:104";
          

    You can obtain the processDefinitionId by querying the available workflows, for example:

          
     {
      "result": [
        {
          "name": "Process Start Auto Generated Task Auto Generated",
          "_id": "ProcessSAGTAG:1:728"
        },
        {
          "name": "Process Start Auto Generated Task Empty",
          "_id": "ProcessSAGTE:1:725"
        },
        ...     
          

    If you specify a _key and a _processDefinitionId, the _processDefinitionId is used because it is more precise.

You can use the optional _businessKey parameter to add specific business logic information to the workflow when it is invoked. For example, the following workflow invocation assigns the workflow a business key of "newOrder". This business key can later be used to query "newOrder" processes.

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
 --data '{"_key":"myWorkflow", "_businessKey":"newOrder"}'
  

15.2.6. Querying Activiti Workflows

The Activiti implementation supports filtered queries that enable you to query the running process instances and tasks, based on specific query parameters. For example, the following query returns all process instances with the business key "newOrder", as invoked in the previous section.

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_queryId=filtered-query
 &businessKey=newOrder"
  

You can query process instances based on the value of any process instance variable by prefixing the variable name with _var-. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_queryId=filtered-query
 &_var-processvariablename=processvariablevalue"
  

The standard Activiti properties can be queried using the Activiti notation, for example, processDefinitionId=managedUserApproval:1:6405. The query syntax applies to all queries with _queryId=filtered-query.

15.3. Managing Workflows Over the REST Interface

In addition to the queries described previously, the following examples show the endpoints that are exposed for managing workflows over the REST interface. The example output is based on the sample workflow that is provided in openidm/samples/workflow.

openidm/workflow/processdefinition

List the available workflow definitions, for example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/processdefinition?_queryId=query-all-ids"
 
{
  "result": [
    {
      "name": "Managed User Approval Workflow",
      "_id": "managedUserApproval:1:3"
    }
  ]
}        
             

List the workflows, based on certain filter criteria, for example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/processdefinition?_queryId=
filtered-query&category=Examples"
 
{
  "result": [
    {
      "name": "Managed User Approval Workflow",
      "_id": "managedUserApproval:1:3"
    }
  ]
}          
        
openidm/workflow/processdefinition/{id}

Obtain detailed information for a process definition, based on the ID. (The ID can be determined by querying all available process definitions). For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/processdefinition/contractorOnboarding:1:3"
 
{
  "key": "managedUserApproval",
  "_rev": "0",
  "formProperties": [],
  "category": "Examples",
  "_id": "managedUserApproval:1:3",
  "processDiagramResourceName": null,
  "description": null,
  "name": "Managed User Approval Workflow",
  "deploymentId": "1"
}        
             
openidm/workflow/processinstance

Obtain the list of running workflows (process instances). The query returns a list of IDs. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET
 "http://localhost:8080/openidm/workflow/processinstance?_queryId=query-all-ids"

{
  "result": [
    {
      "processDefinitionId": "contractorOnboarding:1:3",
      "_id": "4"
    }
  ]
}
             

Obtain the list of running workflows based on specific filter criteria. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET
 "http://localhost:8080/openidm/workflow/processinstance?_queryId=
filtered-query&businessKey=myBusinessKey"
             

Start a workflow process instance. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --data {"_key":"contractorOnboarding"}
 --request POST
 "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
             
openidm/workflow/processinstance/{id}

Obtain the details of the specified process instance. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET
 "http://localhost:8080/openidm/workflow/processinstance/4"

{
  "deleteReason": null,
  "processDefinitionId": "contractorOnboarding:1:3",
  "_rev": "0",
  "startTime": "2012-12-18T22:04:50.549+02:00",
  "startUserId": "user1",
  "_id": "4",
  "businessKey": null,
  "durationInMillis": null,
  "endTime": null,
  "superProcessInstanceId": null
}
             

Stop the specified process instance. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request DELETE
 "http://localhost:8080/openidm/workflow/processinstance/4"
             
openidm/workflow/taskdefinition

Query a task definition based on the process definition ID and the task name (taskDefinitionKey). For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/taskdefinition?_queryId=query-taskdefinition
&processDefinitionId=contractorOnboarding:1:6&taskDefinitionKey=decideApprovalTask"
{
  "dueDate": null,
  "taskCandidateGroup": [
    {
      "expressionText": "manager"
    }
  ],
  "formProperties": [
    {
      "type": {
        "values": {
          "accept": "Accept",
          "reject": "Reject"
...
             
openidm/workflow/taskinstance

Query all running task instances. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/taskinstance?_queryId=query-all-ids"
 
{
  "result": [
    {
      "name": "Contractor Approval",
      "_id": "70"
    }
  ]
}
             

Query task instances based on candidate users or candidate groups. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/taskinstance?_queryId=filtered-query&taskCandidateUser=manager1"
             

or

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/taskinstance?_queryId=filtered-query&taskCandidateGroup=management"
             

Note that you can include both users and groups in the same query.

openidm/workflow/taskinstance/{id}

Obtain detailed information for a running task, based on the task ID. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request GET       
 "http://localhost:8080/openidm/workflow/taskinstance/70"
 
{
  "dueDate": null,
  "processDefinitionId": "contractorOnboarding:1:3",
  "owner": null,
  "taskDefinitionKey": "decideApprovalTask",
  "name": "Contractor Approval",
...
             

Update task-related data stored in the Activiti workflow engine. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --header "If-Match : *"
 --request PUT       
 --data '{"description":"updated description"}'
 "http://localhost:8080/openidm/workflow/taskinstance/70"
             

Complete the specified task. The variables required by the task are provided in the request body. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST       
 --data '{"requestApproved":"true"}'
 "http://localhost:8080/openidm/workflow/taskinstance/70?_action=complete"
             

Claim the specified task. The ID of the user who claims the task is provided in the request body. For example:

$ curl
 --header "X-OpenIDM-Username: openidm-admin"
 --header "X-OpenIDM-Password: openidm-admin"
 --request POST       
 --data '{"userId":"manager1"}'
 "http://localhost:8080/openidm/workflow/taskinstance/70?_action=claim"
             

15.4. Example Activiti Workflows With OpenIDM

This section describes two example workflows - an email notification workflow, and a workflow that demonstrates provisioning, using the browser-based user interface.

15.4.1. Example Email Notification Workflow

This example uses the Activiti Eclipse BPMN 2.0 Designer to set up an email notification business process. The example relies on an SMTP server listening on localhost, port 25.

The example sets up a workflow that can accept parameters used to specify the sender and recipient of the mail.

${fromSender}

Used to specify the sender

${toEmail}

Used to specify the recipient

Once you have defined the workflow, drag and drop components to create the workflow. This simple example uses only a StartEvent, MailTask, and EndEvent.

Email notification process

After creating the workflow, adjust the generated XML source code to use the variables inside the <serviceTask> tag shown in the following listing.

<?xml version="1.0" encoding="UTF-8"?>
<definitions
 xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:activiti="http://activiti.org/bpmn"
 xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
 xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
 xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
 typeLanguage="http://www.w3.org/2001/XMLSchema"
 expressionLanguage="http://www.w3.org/1999/XPath"
 targetNamespace="http://www.activiti.org/test">
 <process id="EmailNotification" name="emailNotification">
   <documentation>Simple Email Notification Task</documentation>
   <startEvent id="startevent1" name="Start"></startEvent>
   <sequenceFlow id="flow1" name="" sourceRef="startevent1"
     targetRef="mailtask1"></sequenceFlow>
   <endEvent id="endevent1" name="End"></endEvent>
   <sequenceFlow id="flow2" name="" sourceRef="mailtask1"
     targetRef="endevent1"></sequenceFlow>
   <serviceTask id="mailtask1" name="Email Notification"
     activiti:type="mail">
     <extensionElements>
       <activiti:field name="to" expression="${toEmail}"
       ></activiti:field>
       <activiti:field name="from" expression="${fromSender}"
       ></activiti:field>
       <activiti:field name="subject" expression="Simple Email Notification"
       ></activiti:field>
       <activiti:field name="text">
         <activiti:expression><![CDATA[Here is a simple Email Notification
         from ${fromSender}.]]></activiti:expression>
       </activiti:field>
     </extensionElements>
   </serviceTask>
 </process>
 <bpmndi:BPMNDiagram id="BPMNDiagram_EmailNotification">
   <bpmndi:BPMNPlane bpmnElement="EmailNotification"
     id="BPMNPlane_EmailNotification">
     <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
       <omgdc:Bounds height="35" width="35" x="170" y="250"></omgdc:Bounds>
     </bpmndi:BPMNShape>
     <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
       <omgdc:Bounds height="35" width="35" x="410" y="250"></omgdc:Bounds>
     </bpmndi:BPMNShape>
     <bpmndi:BPMNShape bpmnElement="mailtask1" id="BPMNShape_mailtask1">
       <omgdc:Bounds height="55" width="105" x="250" y="240"></omgdc:Bounds>
     </bpmndi:BPMNShape>
     <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
       <omgdi:waypoint x="205" y="267"></omgdi:waypoint>
       <omgdi:waypoint x="250" y="267"></omgdi:waypoint>
     </bpmndi:BPMNEdge>
     <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
       <omgdi:waypoint x="355" y="267"></omgdi:waypoint>
       <omgdi:waypoint x="410" y="267"></omgdi:waypoint>
     </bpmndi:BPMNEdge>
   </bpmndi:BPMNPlane>
 </bpmndi:BPMNDiagram>
</definitions>

In Eclipse, select the project, then right click and select Create deployment artifacts to generate the components and package them in a .bar file for deployment in the openidm/workflow directory.

After you deploy the .bar, create a script named openidm/script/triggerEmailNotification.js. The script invokes the workflow.

/*
 * Calling 'EmailNotification' workflow
 */

var params = {
 "_key" : "EmailNotification",
 "fromSender" : "noreply@openidm",
 "toEmail" : "jdoe@example.com"
};

openidm.action('workflow/processinstance', {"_action" : "createProcessInstance"}, params);

You can also invoke the workflow over the REST interface with the following REST command:

$ curl
 --header "X-OpenIDM-Username: openidm-admin" 
 --header "X-OpenIDM-Password: openidm-admin"
 --data '{"_key":"EmailNotification", "fromSender":"noreply@openidm", "toEmail":"jdoe@example.com"}'
 --request POST 
 "http://localhost:8080/openidm/workflow/processinstance?_action=createProcessInstance"
   

To schedule the workflow to be invoked regularly, create a schedule configuration object named openidm/conf/schedule-EmailNotification.json. The following schedule invokes the workflow once per minute.

{
   "enabled" : true,
   "type" : "cron",
   "schedule" : "0 0/1 * * * ?",
   "invokeService" : "script",
   "invokeContext" : {
       "script" : {
           "type" : "text/javascript",
           "file" : "script/triggerEmailNotification.js"
       },
   }
}

15.4.2. Sample Workflow - Provisioning User Accounts

This example, provided in openidm/samples/workflow, uses workflows to provision user accounts. The example demonstrates the use of the browser-based user interface to manage workflows.

15.4.2.1. Overview of the Sample

The sample starts with a reconciliation process that loads user accounts from an XML file into the managed users repository. The reconciliation creates two users, with UIDs user1 and manager1. Both users have the same password (Welcome1).

The sample adds two new business roles to the configuration - employee (assigned to user1) and manager (assigned to manager1).

As part of the provisioning, employees are required to initiate a "Contract Onboarding" process. This process is a request to add a contractor to the managed users repository, with an option to include the contractor in the original data source (the XML file).

When the employee has completed the required form, the request is sent to the manager for approval. Any user with the role "manager" can claim the approval task. If the request is approved, the user is created in the managed users repository. If a request was made to add the user to the original data source (the XML file) this is done in a subsequent step.

The workflow uses embedded templates to build a more sophisticated input form. The form is validated with the server-side policy rules, described in Using Policies to Validate Data.

15.4.2.2. Running the Sample

  1. Start OpenIDM with the configuration for the workflow sample.

    $ cd /path/to/openidm
    $ ./startup.sh -p samples/workflow
  2. Run reconciliation over the REST interface.

    $ curl
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request POST
     "http://localhost:8080/openidm/recon?_action=recon&mapping=systemXmlfileAccounts_managedUser"

    Successful reconciliation returns an "_id" object, such as the following:

    {"_id":"aea493f5-29ee-423d-b4b1-10449c60886c"}

    The two users are added to the repository. You can test this with the following REST query, which shows the two users, manager1 and user1.

    $ curl 
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request GET 
     "http://localhost:8080/openidm/managed/user/?_queryId=query-all-ids"
    
    {
      "conversion-time-ms": 0,
      "result": [
        {
          "_rev": "0",
          "_id": "manager1"
        },
        {
          "_rev": "0",
          "_id": "user1"
        }
      ],
      "query-time-ms": 1
    }
         
  3. Log in to the user interface as user1, with password Welcome1. For information about logging in to the user interface, see Overview of the Default User Interface.

  4. Under "Processes" click "Contractor onboarding process".

  5. Complete the details of the new user, then click Start.

    Contractor onboarding process form
  6. Log out of the UI.

  7. Log in to the UI as manager1, with password Welcome1.

  8. Under "Tasks that are in my group's queue" click "Contractor Approval".

  9. From the drop-down list, select "Assign to me".

    Note that the "Contractor Approval" task has now moved under "My tasks".

  10. Under "My tasks" click "Contractor Approval".

  11. Under Actions, click Details.

    The form containing the details of the contractor is displayed.

  12. At the bottom of the form, select a decision from the drop-down list (either "Accept" or "Reject"), then click Complete.

    If you Accept the new contractor details, the user account is created in the repository. You can check the new account by running the following REST command:

    $ curl 
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request GET 
     "http://localhost:8080/openidm/managed/user/?_queryId=query-all-ids"
    
    {
      "conversion-time-ms": 0,
      "result": [
        {
          "_rev": "0",
          "_id": "manager1"
        },
        {
          "_rev": "0",
          "_id": "user1"
        },
        {
          "_rev": "0",
          "_id": "51afe0f8-94c3-45c5-8c69-319e6ef5981f"
        }
      ],
      "query-time-ms": 1
    }
         

    Display the details of the new user, by running a REST query on the user ID, as follows:

    $ curl
     --header "X-OpenIDM-Username: openidm-admin"
     --header "X-OpenIDM-Password: openidm-admin"
     --request GET     
     "http://localhost:8080/openidm/managed/user/51afe0f8-94c3-45c5-8c69-319e6ef5981f"
    
    {
      "city": "",
      "country": "",
      "address2": "",
      "address1": "",
      "lastPasswordAttempt": "Fri Dec 14 2012 13:54:02 GMT+0200 (SAST)",
      "passwordAttempts": "0",
      "stateProvince": "",
      "postalCode": "",
      "lastPasswordSet": "",
      "jobTitle": "Accountant",
      "department": "Finance",
      "manager": "user1",
      "familyName": "Doe",
      "givenName": "John",
      "userName": "johnd",
      "_rev": "0",
      "_id": "51afe0f8-94c3-45c5-8c69-319e6ef5981f",
      "phoneNumber": "123456789",
      "email": "johnd@example.com",
      "startDate": "12/12/2012",
      "endDate": "12/12/2012",
      "description": "Contract accountant",
      "provisionToXML": "1",
      "accountStatus": "active",
      "roles": "openidm-authorized"
    }     
         

    You can now log in to the UI as the new user (with the details that you specified in Step 5). Under "Notifications" you will see a welcome message indicating the working dates of the new user. If you log in as user1 you are notified of the result of the manager's decision.

    If you specified that the new user should be added to the original data source, you will see that the account was added to the XML file:

    $ cd /path/to/openidm
    $ cat samples/workflow/data/xmlConnectorData.xml
    ...
       >ri:__ACCOUNT__<
          >icf:__DESCRIPTION__<Contract accountant>/icf:__DESCRIPTION__<
          >ri:roles<openidm-authorized>/ri:roles<
          >ri:mobileTelephoneNumber<123456789>/ri:mobileTelephoneNumber<
          >ri:firstname<John>/ri:firstname<
          >ri:manager<user1>/ri:manager<
          >ri:startDate<12/12/2012>/ri:startDate<
          >ri:jobTitle<Accountant>/ri:jobTitle<
          >icf:__UID__<201e0d50-3313-47b3-9bd1-30c1c7dd1cee>/icf:__UID__<
          >icf:__NAME__<johnd>/icf:__NAME__<
          >ri:email<johnd@example.com>/ri:email<
          >icf:__PASSWORD__<MyPassw0rd>/icf:__PASSWORD__<
          >ri:department<Finance>/ri:department<
          >ri:endDate<12/12/2012>/ri:endDate<
          >ri:lastname<Doe>/ri:lastname<
       >/ri:__ACCOUNT__<
    ...
         

    If you declined the approval request, the user will not be created in either data source.

You can see the details of the workflow definition in samples/workflow/workflow/contractorOnboarding.bpmn20.xml.