Workflow Primer – Part 3

In part 2 of this series, we reviewed some of my best practices for the forms engine of the workflow - the part that runs in the browser. The back-end portion of the solution is the Workflow engine, which runs in an ecmascript processor on the server once the workflow forms are submitted.



workflow-img1The request form as you experience it is represented by the "start" activity in a workflow, and additional forms may be instantiated as "approval" activities. But how to we get from here to there? The answer is the workflow itself.

At a technical level, the workflow is shares something in common with the metadirectory engine. Both manage the formation, flow, and transformation of an XML document from start to finish. However, the XML document is a fundamentally different vocabulary, and unlike the metadirectory engine, it is not normally exposed directly.

The way you see this XML is in what workflow calls "flowdata". This is a hierarchy and one which you can customize heavily, but comes with a built-in structure that is easily used. Flowdata is data which flows from one activity to the next.

Although this is not intended to be a reference for the workflow engine, it is important to discuss the various types of activities and how they are used. These are divided into the following categories:

  • User Interaction

  • Data Transformation and External Integration

  • Status and Logging

  • Provisioning

  • Flow Control

User Interaction

These activities include:

  • Start

  • Approval

  • eMail

The start activity encapsulates the request form of the workflow. The approval activity is a similar but separately defined form intended for notifying an approver of their need to approve a workflow. It includes an eMail page, but additionally, a separate eMail activity is also available.

Alternate Use Cases

In addition to its obvious usage, the start activity can be used to simply define an endpoint to be used non-interactively by a metadirectory policy or invoked by a SOAP call from another program.

Similarly, the approval activity can be used with an explicit timeout to delay actions. Approval activities can also be programmatically approved.

Data Transformation and External Integration

The primary mechanisms for modifying data in flow are:

  • Mapping

  • Integration

  • REST

The most commonly used activity is the mapping activity. It is used to transform flow data, to synthesize new flow data, and often to provide a place to configure constant data. The input of the mapping activity is an ecmascript expression which can use flowdata and/or Identity Vault data. The output is a definition of a particular place within the flowdata tree. It can overwrite an existing definition or can define a new one.

Integration activities allow for a web service SOAP call using data from flowdata or IDVault data as its parameters and the retrieval and parsing of responses back into flowdata. The REST activity performs a similar function for RESTful web services.

Alternate Use Cases

One common use case for the integration activity is to expose APIs within the User Application itself. These might be invoked by a special purpose workflow called by the metadirectory engine.

Flow Control

The flow of processing may be controlled by these activities:

  • Condition

  • Branch

  • Merge

  • Finish

Condition activities use an ecmascript expression to determine whether to follow a true or false flow path. These can be used in decisions.

Branch activities allow for the spawning of additional workflow execution threads. This is intended for parallel approvals. The Merge activity provides a point in which all these spawned threads must reach before proceeding as a single one again.

The status activity allows the workflow to identify the overall success or failure of this provisioning flow.

Finally, all workflows to end must eventually reach the finish activity.

Status and Logging

The activities in this group include:

  • Status

  • Log

Status applies a workflow status to the current process. This status is either "approved" or "denied".

Log allows for any data to be included in the audit log and enables custom inclusion of any data determined relevant to the auditing process.


The key provisioning activities include:

  • Entity

  • Entitlement

  • Resource Request

  • Role Request

Entity activities allow direct manipulation of the identity vault data. It does not allow manipulation of connected systems. This is either done via existing metadirectory policies reacting to the modifications of this activity, or via an entitlement activity.

The entitlement activity directly adds or removes entitlements for any driver. This was the first intended way for workflows to manipulate connected systems directly. By defining metadirectory policy that is controlled by an entitlement, this enables the workflow to invoke that policy explicitly.

With the introduction of the roles and resources engine, additional layers of abstraction may be used to interact with connected systems via workflow. Resources are a specific instance of an entitlement bundled with parameter data. Resources may be assigned to users directly but this is not usually an ideal case.

Instead, roles are associated with resources, and the role request activity can start this process. If a role has no approval associated with it, this will grant role assignment, but if there is an approval required, it will simply start the process.

Dealing with Data in Workflow

Unlike the forms engine, which uses javascript variable types, the workflow engine has a number of different object types, and can leverage both ecmascript and java interfaces. Knowing which is which will help you not spin your wheels while creating workflows.

Flowdata.get() vs. Flowdata.getObject()


When browsing through available flowdata from the request form within Designer you will notice the same data exposed as "start" and "start object". When you select something under "start" designer creates a "flowdata.get()" call, whereas when you select "start object" you get a "flowdata.getObject()" call.

The output of the flowdata.get() call is a string containing the first value of a potentially multi-valued component of the flowdata tree. On the other hand, flowdata.getObject() returns a DOM object containing all the values.

The following is an example of iterating through all the values in the flowdata returned by the getObject() method:

function flow2vector(flow)
result = new java.util.Vector();

if (flow)
for (var i = 0; i < flow.size(); i )
v = flow.get(i).getFirstChild().getNodeValue();
if ((v != "true") && (v != ""))
catch (e)

return result;

Writing to flowdata

You would think if you read multi-valued flowdata as a DOM, you would write it back as a DOM. While intuitive, this is not correct.

If you need to output multi-valued data in a mapping activity, you need to convert the output to a "java.util.Vector" object. The example previously provided to demonstrate access to the flowdata object actually accomplishes that.

Handling IDVault.get() in workflow

The IDVault.get() call in workflow looks similar to the version in the form but is a fundamentally different implementation. In the forms, the browser makes a SOAP call to a service called VDX to retrieve data. That interaction is totally server based in the workflow engine. The parameter list is similar, however in the form the first parameter is the field name which is absent from the workflow version. But most significantly, the data types returned differ.

In the form, IDVault.get() returns an ecmascript array of strings, and if it's a single value, that may be treated as a ecmascript string. Within the workflow, the method returns a generic object; the actual data type returned depends on the results.

  • If the method returns no values, the value of the call is null.

  • If the method returns a single value, the call returns a string

  • If more than one value is returned, the call returns a java.util.ArrayList object.

This is perhaps the most frustrating shortcoming in the workflow engine design. To work around this, I created a function called "getObject", which takes the IDVault object and all of its parameters, and consistently returns a java.util.ArrayList object with 0 to N elements.

function getObject(IDVault, dn, className, attributeName) 
var attrVal = IDVault.get(dn , className, attributeName);

if (attrVal == null)
return new;

if (attrVal instanceof java.util.ArrayList)
return attrVal;

newVal = new;
return newVal;

Writing data from IDVault.getObject() to flowdata

In order to accomplish this, it is necessary to transform the ArrayList output of getObject() into a java.util.Vector object:

function arrayList2Vector(al)
var vec = new java.util.Vector();
for (var i = 0; i < al.size(); i )
return vec;

Handling IDVault.query()

Much like IDVault.get(), IDVault.query() removes the form name parameter and returns an ArrayList() object instead of an ecmascript array. For the most part, the usage of this method is a close resemblance between forms and workflow.

A notable exception are queries which take no parameters. In the form, this may be specified as follows:

IDVault.globalQuery(null, "Admins")

In workflow, some parameter must be specified, even if it's empty, which can be done as follows:

IDVault.globalQuery("Admins", { } )

Storing the Workflow ID to enable a programmatic approval

A common use case is to use the metadirectory engine or an external program to programmatically start a workflow. A less common requirement is to have a program make a SOAP call to approve or deny a workflow.

In order to accomplish this, it will be necessary to somehow store or transmit the workflow ID to the program which will be processing the approval activity. One common way this can be accomplished is by storing the workflow ID on the user object in an entity activity. The approval flow can remove the value later once the workflow approval is completed.


The workflow engine is a powerful and useful tool in the IDM architects arsenal. A little knowledge about its quirks and hint of methodology can go a long way to enabling rapid development and a reliable deliverable.


How To-Best Practice
Comment List