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.
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.
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.
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 directory. A sample workflow
(/path/to/openidm/workflowexample.bpmn20.xml) is provided in the
directory. Copy this workflow to the
/path/to/openidm/samples/misc
directory to test the workflow integration./path/to/openidm/workflow
$ 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]
]
]
You can set up integration with a remote Activiti engine, as described in the following steps.
Download and install OpenIDM, as described in the Installation Guide.
Download and unzip the Activiti zip file
(activiti-5.10.zip) from
Activiti Downloads page.
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
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.
Set up the default Activiti demo.
$ cd /path/to/activiti/setup/
$ ant demo.start
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.
Configure Tomcat to operate with OpenIDM.
Stop Tomcat.
$ cd /path/to/activiti/setup/
$ ant tomcat.stop
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/
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/
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>
Restart Tomcat.
$ cd /path/to/activiti/setup/
$ ant tomcat.start
Check that Activiti Explorer is running on localhost:9090/activiti-explorer, as you did in the previous section.
Configure OpenIDM to use the remote Activiti engine instead of the local, bundled Activiti engine.
Copy the workflow.json configuration file to
the OpenIDM configuration directory.
$ cd /path/to/openidm/
$ cp samples/misc/workflow.json conf/
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"
}
}
Start up OpenIDM.
$ cd /path/to/openidm/ $ ./startup.sh
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"
Log in to the Activiti Explorer of the remote Activiti engine (with the default username (kermit) and password (kermit).
Install the sample workflow (example.bpmn20.xml).
In Activiti Explorer, click Manage.
From the Deployments menu, select Upload New.
Navigate to the sample workflow (/path/to/openidm/samples
/misc/example.bpmn20.xml)
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).
Test the integration with Activiti Explorer.
Click Processes and select Osgi Process from the list of process definitions.
Click Start Process.
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.
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.
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.
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.
Define your workflow in a text file, either using an editor, such as Activiti Eclipse BPMN 2.0 Designer, or a simple text editor.
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.
Copy the .bar file to the
openidm/workflow directory.
Invoke the workflow using a script (in
openidm/script/) or directly using the REST interface.
For more information, see
Invoking Activiti Workflows.
You can also schedule the workflow to be invoked repeatedly, or at a future time. For more information, see the Scheduler Reference
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"}'
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.
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/processdefinitionList 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/processinstanceObtain 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/taskdefinitionQuery 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/taskinstanceQuery 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"
This section describes two example workflows - an email notification workflow, and a workflow that demonstrates provisioning, using the browser-based user interface.
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.
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"
},
}
}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.
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.
Start OpenIDM with the configuration for the workflow sample.
$ cd /path/to/openidm $ ./startup.sh -p samples/workflow
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
}
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.
Under "Processes" click "Contractor onboarding process".
Complete the details of the new user, then click Start.
![]() |
Log out of the UI.
Log in to the UI as manager1, with password
Welcome1.
Under "Tasks that are in my group's queue" click "Contractor Approval".
From the drop-down list, select "Assign to me".
Note that the "Contractor Approval" task has now moved under "My tasks".
Under "My tasks" click "Contractor Approval".
Under Actions, click Details.
The form containing the details of the contractor is displayed.
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.