BPM and REST Services

REST Integration

From IBPM 7.5 on-wards, a REST interface has been formally provided for the product. REST is a protocol where client requests can be transmitted over an HTTP connection to achieve queries and work on the server. The detailed documentation for the REST APIs can be found in the IBM online Knowledge Center.

When making a REST request, HTTP provides an option to supply the verb or command. These are prescribed by the HTTP protocol and include:

  • GET
  • POST
  • PUT
  • DELETE
  • others

Take care to use the correct REST HTTP command that is associated with the function that is to be performed. Typically commands that retrieve data use the HTTP GET while commands that update or create some BPM resource use POST or PUT.

Note that some requests, specifically PUT and DELETE, may not be allowed to pass through firewalls. A solution to this is to add an HTTP header to the REST request with:

x-method-override = PUT|DELETE

or

x-http-method-override = PUT|DELETE

And send the request over a POST request which will be allowed to pass. For BPD related REST requests, a URI parameter can be added … eg.

http://....?&x-method-override=PUT

For some REST command, the command may simply be too long if passed as a URL. This happens because the query parameters are too much. The query parameters are the parts following the "?" in the path of the URL. A solution to this is to send the REST request as a POST, set the x-http-method-override HTTP header to be the command and place the parameters of the REST request in the body of the POST HTTP request. The HTTP Content-Type header should be set to "application/x-www-form-urlencoded".

Yet another way of sending data to the server is to use POST and set the content to be "multipart/form-data".

For example, setting the Content-Type to be:

multipart/form-data; boundary=-----------------------------4827543632391

then a body could be:

-----------------------------4827543632391
 Content-Disposition: form-data; name="instanceId"
 123
 -----------------------------4827543632391
 Content-Disposition: form-data; name="name"
 myname
 -----------------------------4827543632391
 Content-Disposition: form-data; name="docType"
 file
 -----------------------------4827543632391
 Content-Disposition: form-data; name="data"; filename="MyDoc.txt"
 Content-Type: text/plain
 Hello
 -----------------------------4827543632391--

To use this multipart/form-data style can be quite tricky. However, if called from Java, the Apache HTTP Components may come to our aid.

A module in this offering is called MultipartEntity. An instance of this object can have multiple "parts" added to it with the "addPart()" method. A part appears to be of data type ContentBody which has two interesting concrete implementations for us:

  • StringBody – A string value
  • ByteArrayBody – An array of bytes

From this, it appears that we can build a MultipartEntity object and add to that a series of "parts". Once done, we can then use that Multipart entity as the payload of a REST request. Each part has an associated "name" which is supplied in the addPart() method.

See also:

The REST Functions

The API exposed by the product includes a rich set of capabilities:

Process Model: get
Process Applications: get
Process Applications: post Create a new Process Application from a BPMN 2.0 archive
Toolkits: get
Toolkits: post
Process: start
Process: send message
Process Instance: get
Process Instance: suspend
Process Instance: resume
Process Instance: terminate
Process Instance: update process instance
Process Instance: update due date
Process Instance: start adhoc
Process Instance: delete document
Process Instance: add comment
Process Instance: fire timer
Process Instance: add document
Process Instance: update document
Process Instance: delete document
Process Instance: evaluate JavaScript Execute JavaScript within the context of a process
Process Instance Queries: get
Process Instance Query Attributes: get
Process Instance Query Entity List: get
Process Instance Query Entity List Count: get
Service Model: get
Service: start
Service: currently running
Service: get data
Service: stop
Service: resume
Service: set data
Service: evaluate JavaScript
Task Template: get
Task Template Client Settings: get
Task Template Queries: get
Task Template Query Attributes: get
Task Template Query Entity List: get
Task Template Query Entity List Count: get
External Activity Model: get
Task: bulk claim
Task: bulk cancel
Task: get next
Task Actions: get
Task Instance: get
Task Instance: start task
Task Instance: assign task
Task Instance: update
Task Instance: finish
Task Instance: claim
Task Instance: cancel
Task Instance Client Settings: get
Task Instance Queries: get
Task Instance Query Attributes: get
Task Instance Query Entity List: get
Task Instance Query Entity List Count: get
Exposed Items: get
Search Metadata: get
Search: perform custom search
Performance Query: get
Performance Instance Query: get
Users: get
User: get
User: put
Groups: get
Group: get
Systems Metadata: get
Asset List: get
Branch Snapshot List: get
Project Named Snapshots List: get
Snapshot Change History: get
Compare History: get
Process Application Settings: get

Handling REST errors

Not all requests to IBM BPM will always succeed. Errors can be returned. The format of a an error is as follows:

{
   status: "error"
	 Data: {
	     errorMessage: "Text of message",
			 errorMessageParameters: [ // array of parameters // ],
			 errorNumber: "Error message number",
			 exceptionType: "Java exception name"
			 responses: // unknown //
   }
}

The REST API Tester

Baked into IBPM is a fantastic tool for testing REST APIs. It is a web based application that can be reached at:

http://<hostname>:<port>/bpmrest-ui

When launched from a browser, it shows a list of the categories of the different REST requests:

Selecting an entry shows the details of that entry and allows values for the parameters to be supplied. From there, an Execute Call button can be pressed which executes a live call to the server and returns the data from the server for examination.

The data can be selected to be returned as either JSON or XML.

Alternatives to the REST API Tester tool include the popular soapUI and the FireFox plug-in called RESTClient.

After installing RESTClient, it can be opened in the FireFox environment and shows a window that looks as follows:

Working with REST Search Queries

One of the more interesting REST APIs is called "Search" and is generically available at:

/rest/bpm/wle/v1/search/query

This request is available through both PUT and POST HTTP REST commands but surprisingly not through GET even though this seems like an ideal and logic candidate for a GET request.

The operation can take a number of parameters as query strings. These include:

Name Description
columns See description below. A comma separated list of column names.
condition See description below.
sort
secondSort
organization There appears to be two distinct query return type organizations. One returns task instances and the other returns process instances. This parameter declares which type of search should be performed. The choices are "byTask" or "byInstance".
saveAsName If this search is to be saved for later re-use then a name value may be supplied here.
run
shared

The columns is a comma separated list of column names of data that can be returned. The list of columns that can be supplied is itself available from a REST request called:

/rest/bpm/wle/v1/search/meta/column

As of IBPM version 8.5 the list looks as follows:

  • assignedToUser
  • assignedToRole
  • instanceName
  • instanceId
  • bpdName
  • instanceDueDate
  • instanceCreateDate
  • instanceModifyDate
  • instanceStatus
  • instanceSnapshot
  • instanceProcessApp
  • taskDueDate
  • taskPriority
  • taskSubject
  • taskStatus
  • taskReceivedDate
  • taskClosedDate
  • taskSentTime
  • taskReadTime
  • taskReceivedFrom
  • taskClosedBy
  • taskActivityName

In addition to the column names listed above, there are a set of additional columns that are commonly returned. Note, do not include these columns in the search columns. These are:

Property Description
taskId The ID of the task
taskAssignedTo Who is the ?? assigned to. Can be null or not present.
assignedToUser Who is the ?? assigned to. Can be null or not present,
taskAttachedExtActivityRef
taskAttachedInfoPathFormRef

The format of a returned JSON structure looks as follows:

{
	status: "200",
	data:
	{
		data:
		[
			{
				<columnName>: <columnValue>,
				<columnName>: <columnValue>,
				…
				<columnName>: <columnValue>,
			},
			…
			{
				<columnName>: <columnValue>,
				<columnName>: <columnValue>,
				…,
				<columnName>: <columnValue>,
			}
		],
		organization: {"byTask"|"byInstance"},
		autoColumns:
		[
				"assignedToUser",
				"instanceId",
				"instanceStatus",
				"taskAssignedTo",
				"taskAttachedExtActivityRef",
				"taskAttachedInfoPathFormRef",
				"taskCreatedByBpdFlowObjectId",
				"taskCreatedByBpdId",
				"taskId"
		]
	}
}

As can be seen, the most interesting aspect of this is the data field which is an array of objects where each object is a set of properties corresponding to the retrieved "columns". The "autoColumns" are the names of additional columns returned beyond those explicitly requested.

The condition part of the REST request allows us to filter or constrain the records returned on a query. A condition takes the form:

<columnName>|<operation>|<value>

The allowable operations are:

  • Equals
  • NotEquals
  • Contains
  • StartsWith
  • LessThan
  • GreaterThan

multiple conditions can be supplied and these logically "ANDed" together. There is no deeper query mechanism than this (for example logical "ORs"). Not all column names are supported for condition evaluation. A REST request of the form:

/rest/bpm/wle/v1/search/meta/constraintColumn

returns the list of column names that may be used in conditions. As of 8.5 these are:

  • assignedToUser
  • assignedToRole
  • bpdName
  • instanceCreateDate
  • instanceDueDate
  • instanceId
  • instanceModifyDate
  • instanceName
  • instanceProcessApp
  • instanceStatus
  • instanceSnapshot
  • taskActivityName
  • taskDueDate
  • taskPriority
  • taskStatus
  • taskSubject

An example condition might be:

  • instanceProcessApp|Equals|A110822 – True if the Process App is "A110822"
  • bpdName|Equals|<Name> and taskActivityName|Equals|<Name> – True for a specific task type within a given BPD type

Another REST exposed service that can be used in conjunction with searches is called Search Meta Data and is exposed at:

GET /rest/bpm/wle/v1/search/meta/type

The type parameter defines what type of search data is desired. As of 7.5.1, the following types and their content are defined:

  • column - The names of the columns that can be included as columns to be returned

  • constraintColumn - The names of columns that can be included in constraint expressions

  • taskStatus – The different status that a task may have. Currently these are:

New_or_Received Actioned Alert Answered_Help_Request Closed Comment Deleted Followed Forwarded Help_Request Ignored_Help_Request New Received Replied Sent Special

  • businessData – The names of business data fields that can be returned as columns

  • savedSearch – The names of saved searches

  • instanceStatus – The name of statuses of process instances. Currently these are:

Active Completed Did_not_Start Failed Suspended Terminated

priority – The names of allowable priority settings. Currently these are:

Highest High Normal Low Lowest

There is another aspect to the story that we can choose to learn or ignore. The API just described provides a relatively highly level access to performing searches. It makes sense. However, the careful reader will have seen that we can create "named" saved searches. Unfortunately, if we again look closely at the API, you won't find any way to execute a previously saved search.

That seems mighty odd.

The history of how we got to this state is unknown but there does appear to be some clues and also ways in which we can indeed use these saved searches.

A saved search can be of one of the following types:

  • Process Instances
  • Process Templates
  • Tasks

Corresponding to each of these three types, there are distinct additional APIs that can be used which also result in searches being performed. These other searches have different parameters but included in this mix, is the ability to invoke a named save search.

For the three types, the following REST APIs are available:

For processes:

  • Process Instance Queries – Return a list of saved searches specifically for the process instances type
  • Process Instance Query Attributes – Given a saved search name, return the details of the search
  • Process Instance Query Entity List – Given a saved search name, execute the search
  • Process Instance Query Entity List Count – Given a saved search name, determine how many entries would be returned

Working with REST Task Instance Queries

This is an area that the author is still researching but one which appears to be of high importance. The concept appears to be that a query can be executed to retrieve task information but the responses seem very different from simple searches. It appears that there is a wealth of possibilities here. The general syntax is:

GET /rest/bpm/wle/v1/tasks/query/{queryName}?<parameters>

  • selectedAttributes – string -
  • interactionFilterString – One of the following values:

WORK_ON WORK_ON_ACTIVE ASSESS_AVAILABLE ASSESS_AND_WORK_ON CHECK_COMPLETED BROWSE_ALL

  • queryFilter – string -
  • searchFilter – string -
  • processAppName – string -
  • sortAttributes – string -
  • offset – integer -
  • size – integer -
  • filterByCurrentUser – boolean

Each search has attributes/items and each attribute is defined with:

  • name
  • displayName
  • description
  • isArray
  • sourceAttribute
  • content
  • sourceQueryTableIdentifier
  • isSortable
  • isFilterable

An example of an IBM existing saved search is "IBM.DEFAULTALLTASKSLIST_75" which contains:

Name Column
TAD_DISPLAY_NAME taskSubject
TAD_DESCRIPTION taskNarrative
DUE taskDueDate
ACTIVATED taskReceivedDate
PRIORITY taskPriority
STATUS taskStatus
STATE taskStatus
ORIGINATOR taskReceivedFrom
COMPLETED taskClosedDate
OWNER assignedToUser
ASSIGNED_TO_ROLE_DISPLAY_NAME assignedToRoleDisplayName
NAME taskActivityName
TKIID taskId
AT_RISK_TIME taskAtRiskTime
IS_AT_RISK taskIsAtRisk
PI_PIID instanceId
CONTAINMENT_CTX_ID instanceId
PI_NAME instanceName
PI_DISPLAY_NAME instanceName
PT_PTID bpdid
PT_DISPLAY_NAME bpdName
PROCESS_APP_ACRONYM instanceProcessApp
SNAPSHOT_NAME instanceSnapshot
SNAPSHOT_ID instanceSnapshotId
KIND
PI_DUE instanceDueDate
PI_CREATE instanceCreateDate
PI_MODIFY instanceModifyDate
PI_STATE instanceStatus
PI_STATUS instanceStatus
ASSIGNED_TO_ROLE assignedToRole
SENT_TIME taskSentTime
READ_TIME taskReadTime
CLOSED_BY taskClosedBy

Working with REST Task Instances

There are a set of REST requests that will work with instances of tasks. These include the following operations:

  • Get the details of a task
  • Start a new task
  • Assign a task to a user or group
  • Update the due date or priority of a task
  • Complete/close a task
  • Claim a task against a user
  • Cancel a task

All of these commands start with the general prefix of:

/rest/bpm/wle/v1/task/{*taskId*}

The taskId value can potentially be retrieved from a preceding query/search call.

Getting Task and Instance details through REST

The method to get the details of task look as follows:

GET /rest/bpm/wle/v1/task/{taskId}[?parts={string}]

where parts can be one of "data", "all" or "none". The default is "all". An example response is shown next:

{
   "status": "200",
   "data":    {
      "activationTime": "2011-08-31T18:14:53Z",
      "clientTypes": ["IBM_WLE_Coach"],
      "completionTime": null,
      "containmentContextID": null,
      "description": null,
      "displayName": "Step: Call EA1",
      "dueTime": "2011-08-31T19:14:53Z",
      "kind": "KIND_ORIGINATING",
      "lastModificationTime": "2011-08-31T18:14:53Z",
      "name": "Call EA1",
      "originator": "tw_admin",
      "owner": null,
      "priority": 30,
      "startTime": "2011-08-31T18:14:53Z",
      "state": "STATE_RUNNING",
      "tkiid": "1223",
      "piid": null,
      "status": "Received",
      "priorityName": "Normal",
      "assignedTo": "All Users_T_da7e4d23-78cb-...b2262",
      "assignedToType": "group",
      "data":
			{
         "bpdToken":
				{
            "bpdInstanceID": {"data": 1422},
            "tokenID": "2"
				},
         "variables":
				{
					"in1":
					{
            	"f1": "f1Val",
	            "f2": "f2Val",
	            "f3": "f3Val",
	            "f4":
						{
							"x": "hi",
							"y": 0,
							"z": false
						}
				}
			}
		},
      "externalActivityID": "60.0b902a52-8df2-44ed-85e2-04bbd980b01d",
		"serviceID": "…",
		"nextTaskId": "…",
		"processInstanceName": "…",
		"isAtRisk": "…", 
		"collaboration":
	}
}

Some of the fields in this data structure need explanation:

Field Name Description
activationTime
atRiskTime
clientTypes The type of client we can use. Choices are "IBM_WLE_Coach" and "IBM_WLE_External_Activity".
completionTime
containmentContextID
description
displayName
dueTime
isAtRisk A flag that indicates that this task is at risk.
kind -
lastModificationTime
name
originator
owner
priority
startTime
state - - -
tkiid The Task instance id
piid The Process instance id
processInstanceName
status - -
priorityName
assignedTo
assignedToDisplayName
assignedToType - -
data
processData
serviceID The serviceID field is extremely useful. This is the identifier for the service that created the task. Through this, we can get service description and from this, the expected input and output data types.
flowObjectID
nextTaskId
collaboration

One of the most important aspects of the Task data structure is that it contains the variables passed in and/or returned from the task. Ignoring the rest of the structure, these variables can be found at:

{
	data:
	{
		data:
		{
			variables:
			{
				varName:
				{
					fieldName: …
					fieldName: …
				}				
			}
		}
	}
}

The field values are pretty much what you would expect. They are strings for String, numbers for numbers and nested JSON objects for deeper data types … however … arrays (lists) seem somewhat different.

Consider a data type that looks as follows:

This is a data type that contains a field which is an array of strings. If we have a task that has an input variable of this type, what we find is that the Task data returned looks as follows:

{
	data:
	{
		data:
		{
			variables:
			{
				in1:
				{
					f1:
					{
						items: "[\"a\",\"b\"]",
						selected: "[]"
					}
				}				
			}
		}
	}
}

When a query is made to the run-time to retrieve the tasks/process instance, it is made as a specific user. What this means is that only those tasks for that user are actually shown. This means that it is not possible (using the REST APIs) to retrieve a list of tasks/processes for all users. The JavaScript API called TWSearch allows for the query of all tasks/instances without regard to who owns or can work on them.

Getting a template for a task

There is a REST call that retrieves a template for a task. At a high level it looks as follows:

GET /rest/bpm/wle/v1/taskTemplate/{templateId}

What is a templateId?

Finishing a Task

Another Task oriented REST request available to us performs the job of completion of a task. The format of this command is one of:

  • PUT /rest/bpm/wle/v1/task/{*taskId*}?action=finish&params={*json*}
  • POST /rest/bpm/wle/v1/task/{*taskId*}?action=finish&params={*json*}

To set the values of the variables, what we want to do is get a list of all the expected output variables of that task. Imagine, for example, a task that has an output variable called "out1" of data type "BO1". The completion of an instance of this task would then be achieved by returning a JSON object that contains a property called "out1" (which is the same name as the variable) where this property contains a JSON child object representation of the data.

An example to complete this task would then be:

/rest/bpm/wle/v1/task/1260?action=finish&params={"out1":{"a":"a1", "b":"b1","c":"c1"}}

Note that the action=complete is a synonym for action=finish.

Experience seems to show that for data types of type List, the data coming back is of the format:

{
	"selected":
	[
	],
	"items":
	{
	}
}

Where selected is an array of integers of ordinal items selected and items is an array of items in the array. When setting a response of a list, experience seems to be showing that items can be set but not the selected entries. Attempting to set selected is resulting in errors.

If we have chained tasks, a property called "nextTaskId" contains an array of taskIds. Quite why this is an array and not a single task is still a mystery. If there is no next taskid, the array length is zero.

Starting a Task

The Start Task REST request first struck me as an odd thing. It has a mandatory parameter … a taskId. This confused me for the longest time. Why would we start a task if it already existed? What does it mean to start a Task? After a lot of play testing and an awful lot of help from others, something clicked. The idea of "Starting a Task" is synonymous with the idea of "Starting to work on a task". This is opposed to the other interpretation which is “creating a task instance”. Starting to work on a task comes into play when one thinks of measuring process metrics such as how long did it take someone to work upon a task.

Consider two distinct tasks both of which complete 4 hours after the process created them. In one task, a user started working on it as soon as it was created and it took him 4 hours to complete the work associated with it. This resulted in a wall clock time of 4 hours from when the task was created to when it was finished. For the second task, the user started working on it 3 hours and 30 minutes after the task was created and finished his task 30 minutes later. Again this resulted in a wall clock time of 4 hours from when the task was created to when it was finished. Should we consider both tasks the same? The answer is no. The first task took a person 4 hours while the second task took a person 30 minutes. This obviously means that the tasks were not of the same nature. More, if one is looking to improve the process, one would want to focus on tasks that take longer to complete and simple wall-clock time of how long it took for the activity to complete is not always a good measure since we shouldn't assume that the task is worked on as soon as it is created.

The REST API to flag a Task as started is:

POST /rest/bpm/wle/v1/task/{*taskId*}?action=start

where the taskId is the identifier of an existing task.

An example return from this call looks as follows:

{
	"data":
	{
		"return":
		{
			"serviceStatus": "coach",
			"data": "{\"var1\":\"Hello\"}",
			"coach": "<Form xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n  <FormTitle>IBM BPM Coach<\/FormTitle>\r\n  <Layout id=\"section\" styleClass=\"\">\ ...  <\/Layout>\r\n<\/Form>",
			"step": "Untitled1",
			"coachEvals":
			{
			},
			"actions":
			{
				"str":
				[
					"ButtonGroup0_Button0",
					"ButtonGroup0_Button1"
				]
			},
			"key": "1456"
		}
	}
}

The return data from the Start request is very interesting. The first thing to note is that it returns the XML representation of the Coach itself before being passed through the XSLT conversion to make it HTML. In principle this could then be "parsed" by some GUI generation or interpretation tool to build a new UI. In practice though, my opinion is that this would not be a good idea. The XML representation of the Coach may change in future releases.

Another return is the current value of all the variables in the Service. This appears to be a single String that is JSON encoded.

In the "actions" section is a list of the identities of the buttons which can cause the Coach to complete. These can later be used to cause the Coach to complete through other REST API commands.

Claiming a task

When a task is created, it may be associated with a Team. This is a set of potential owners. When one of those potential owners looks at their task list, they will see the task available to them to work upon. What we want to happen is that when a specific user works on a task, that task should no longer be available to the other potential owners. Another way of saying this is that we want a task to be "claimed" by a particular user. Once it has been claimed, it shouldn't be able to be claimed by another user.

There is a REST API for claiming a task. It is:

POST /rest/bpm/wle/v1/task/{taskId}?action=claim

Re-assigning a task

A task can be re-assigned to a different user or group of users. This is achieved with the following REST command:

PUT (orPOST) /rest/bpm/wle/v1/task/{*taskId*}?action=assign[&toMe={boolean}][&back={boolean}][&toUser={string}][&toGroup={string}][&parts={string}]

The taskId is the identifier of the task to be re-assigned.

The parts parameter describes what data should be returned from this specific call.

The other parameters describe the new user or groups to which the task should be assigned.

  • toMe=true – Assign this task to the user that is making the REST call
  • back=true – Assign this task back to the original owner
  • toUser=string – Assign this task to the named user
  • toGroup=string – Assign this task to the named group

There appears to be mysterious rules governing who can perform an assignment of a given task and to whom it can be assigned. Read the previous sentence again carefully as it takes some thought to understand that there are actually two considerations at play there. Let us look at them both.

Given an arbitrary task X, the first question is "Can I actually perform an assignment upon it?". The answer to that appears to be "yes, but only if you are either currently assigned to the task or you belong to a group to which the task is assigned".

The next question is "To whom can I assign the task?". The answer to that appears to be "Another user who is also in a group that you yourself are also a member of or to a group that you are a member of".

Getting Task variable values

When a task exists, it may variables associated with it. There is a REST API that can be used to retrieve the values of those variables. At a high level it is:

GET /rest/bpm/wle/v1/task/{*taskId*}?action=getData&fields=*fieldName*

An example instance of a result would be:

{
   "status": "200",
   "data":    {
      "result": "{\"xyz\":\"Neil\"}",
      "resultMap": {"xyz": "Neil"}
   }
}

Although the documentation calls the parameter "fields", this is really a pretty bad name. What the "fields" represents are the variables within the task. Multiple variables can be returned in one call simply by having multiple values for the fields parameter separated by commas:

fields=var1,var2,var3

The response data consists of two parts. The first called "result" is a JSON encoded representation of the data. The second is a property called "resultMap" which is an object that contains a single property for each variable requested.

Setting Task variable values

One a task is created but before it is completed, it is legal to set the values of the variables of that task through REST. The API to achieve this is:

POST /rest/bpm/wle/v1/task/{taskId}?action=setData&params=\<JSON String\>

The parameter is a single JSON string that represents a single JavaScript object. Each property of that object will correspond to a variable associated with the task.

Getting the client details of a task

When a task is associated with a Coach, we can retrieve some client details for that task. This is itself an additional REST call:

GET /rest/bpm/wle/v1/task/{taskId}/clientSettings/IBM\_WLE\_Coach

This returns the following data:

{
	status: "200",
	data: {
		url:"http://localhost:9080/teamworks/process.lsw?zWorkflowState=1&zTaskId=1749&zResetContext=true"
	}
}

The important property is called "url". This contains the URL that can be opened to show the task.

Working with REST Processes

Through the REST APIs we have the ability to work with Processes and instance of processes.

Starting a process from REST

A Process Instance can be started with the Process Resource POST (start) method which generally looks like this:

POST /rest/bpm/wle/v1/process?action=start&bpdId={string}{[&snapshotId={string}]|[&processAppId={string}]}[params={string}]

Only one of snapshotId or processAppId should be supplied. It is mandatory that one of them be supplied to identify which process should be started.

The parameters are GUIDs.

The values for the start REST command can be retrieved from the Exposed Items (with filter) resource:

GET /rest/bpm/wle/v1/exposed/process

From the exposed details, the fields of interest are:

REST term parameter Exposed Value
bpdId itemID
snapshotId snapshotID
processAppId processAppID

There is also a property within the data returned on exposed processes which is called "startURL" which can be used to directly start the process. For example:

/rest/bpm/wle/v1/process?action=start&bpdId=25.acbeda41-aa7c-4748-adb0-e3c031bca280&processAppId=2066.06402192-a621-49fc-a9b3-65976c821c3f

An example response from the start request may look as follows:

{
	status: "200",
	data:
	{
		creationTime: "2012-01-07T02:49:09Z",
		description: null,
		executionState: "Completed",
		lastModificationTime: "2012-01-07T02:49:09Z",
		name: "BondProcess:231",
		piid: "231",
		processTemplateID: "25.895c6548-91ef-4862-916b-5cec3460e79d",
		processTemplateName: "BondProcess",
		processAppName: "Surity",
		processAppAcronym: "A111229",
		snapshotName: null,
		snapshotID: "2064.b1e4c8b4-b742-4c0b-a1b6-74a2fb4cc35a",
		dueDate: "2012-01-21T02:49:09Z",
		comments:
		[
		],
		tasks:
		[
		],
		documents:
		[
		],
		actionDetails: null,
		data: ""{}"",
		variables:
		{
		},
		executionTree:
		{
			executionStatus: "2",
			root:
			{
				name: "BondProcess",
				nodeId: "1",
				children: null,
				createdTaskIDs: null
			}
		},
		diagram:
		{
		}
	}
}

Getting details of a process instance using REST

The details of a process instance can be retrieved through a REST call if we know the process instanceId. The syntax for the REST request is as follows:

GET /rest/bpm/wle/v1/process/{*processInstanceId*}

Within the REST API Tester, this function is known as:

WLE REST APIs > Process API > Current State

status: "200",
data:
{
	creationTime: "2012-04-20T15:51:02Z",
	description: null,
	executionState: "Active",
	lastModificationTime: "2012-04-20T15:51:27Z",
	name: "BPD1:943",
	piid: "943",
	processTemplateID: "25.218bd752-b612-4c8b-9fc7-e1a69ac6e925",
	processTemplateName:	"BPD1",
	processAppName: "Attachment Security",
	processAppAcronym: "A120420",
	snapshotName: null,
	snapshotID: "2064.0a006243-cb2d-45fa-aa4b-cde8d8c05ecc",
	dueDate: "2012-05-04T15:51:02Z",
	comments:[],
	tasks:[],
	documents:[
	{
		name: "dddd",
		type: "FILE",
		date: "2012-04-20T15:51:22Z",
		length: 6,
		ID: "103"
	}],
	actionDetails: null,
	data: ""{}"",
	variables:
	{
	},
	executionTree:
	{
		executionStatus: "1",
		root:
		{
			name: "BPD1",
			nodeId: "1",
			children: [
			{
				name: "Untitled1",
				nodeId: "4",
				children: null,
				flowObjectId: "bpdid:56d35d2f221c8d0e:-2c8e90b7:136a1cc0df6:-7e2a",
				tokenId: "4",
				createdTaskIDs: ["884"]
			}],
			createdTaskIDs: null
		}
	},
	diagram:
	{
	}
}

Let us look at the executionTree section. Examination holds the following to be the best understood model of this data:

{
	executionStatus: "1"		// Unknown
	root: {
		name: "Process Model Name",
		nodeId: Integer,			// Unknown
		children: {},
		createdTaskIDs: 			// Unknown
	}
}

The children items appear to have the following format

{
	name:
	nodeId:
	children: {},
	flowObjectId:							// Step ID of the BPD step that token is upon
	tokenId: String,						// Id of the token
	createdTaskIDs: Array of String	// TaskIds created for this step
}

Boiling this down to the commonly asked for function. What if I want to know where within my current process I currently am?

It seems that getting the Process Instance data and drilling down to:

executionTree.root.children[\*]

will return the meat of what we are looking for.

Getting details of a process model from REST

GET /rest/bpm/wle/v1/processModel/{bpdId}?snapshotId={String}

This returns:

  • Name of process
  • Data model including inputs and outputs

Starting a UCA from REST

A UCA can be fired through a REST request. The triggering of a UCA can be used to start a process through a Start Message Event or unblock a process waiting on an Intermediate Message Event.

POST /rest/bpm/wle/v1/process?action=sendMessage&message={string}

The format of the message is:

<eventmsg>
<!-- The process app acronym and event name are required: The snapshot and UCA name are optional -->
	<event processApp="[acronym]" snapshot="[snapshot_name]" ucaname="[UCA_name]">[eventMessageId]</event>
	<!--Optional: The name of the queue for the event to run in -->
	<queue>[queue name]</queue>
	<!--Any parameters the UCA may require -->
	<parameters>
		<parameter>
			<key>param1</key>
			<value>![CDATA[value_for_param1]]</value>
		</parameter>
		<parameter>
			<key>param2</key>
			<value>value_for_param2</value>
		</parameter>
	</parameters>
</eventmsg>

The response from the POST request indicates whether or not the request message was received:

{
	"status": "200",
	"data": {"messageSent": true}
}

An example of current usage of this REST request is to start a new instance of a BPD process with data.

It should be noted that the "eventMessageId" property is the identity of the UCA … see:

Moving a token within a process using REST

The concept of a token is the step within a BPD process instance that is the "current" step. The REST API provides the capability to "move" tokens from one step to another.

POST /rest/bpm/wle/v1/process/{instanceId}?action=moveToken&tokenId={string}&target={string}

The tokenId is a simple numeric value (eg. 4) and is obtained from a process instance query. The target is the IBM BPM id of the step in the process (eg. bpdid:56d35d2f221c8d0e:-3cac44a9:13b35102749:-7de2). This can also be determined from a process instance query.

Retrying a failed instance

GET /rest/bpm/wle/v1/process/{instanceId}?action=retry

Executing JavaScript in the context of a process from a REST request

An unusual REST API is exposed that allows an arbitrary fragment of JavaScript to execute within the context of a process. The API is defined as

POST /rest/bpm/wle/v1/process/{instanceId}?action=js&script=*script*

In order to be able to execute this command, the enable-javascript-execution flag must be set to true. If it is not set to true, the REST request returns "CWTBG0529E: Authorization Error, Javascript Expression execution is disabled". This flag can be found in 99Local.

An example use of this call would be to set the value of a process variable.

It was mentioned that this is an unusual API request as it allows for arbitrary code execution within the context of a process. At present (8.5.5, 09/14), once this flag is on, anyone and everyone is entitled to run the JavaScript and hence security is compromised.

In general, I would recommend staying away from this API. The opportunity for breaking a process is high, there is no obvious auditing or tracking on this command and reviewing a BPMN diagram to understand what the process should do is "deviated" by using this API. If arbitrary code can be executed in the context of a process, working back in the path of such a process from the diagram won't show you how a result was reached.

Updating a variable within a BPD instance

Consider a running BPD instance. What if we want to modify the value of a variable that is contained within it? We can do this from the REST API called Process Instance Variable Resource". The API looks as follows:

POST /rest/bpm/wle/v1/process/{instanceId}/variable/{name}

where the body of the request is a JSON value.

Listing and starting Ad-Hoc Events from REST (pre-8.5.5)

The API request called:

GET /rest/bpm/wle/v1/process/{instanceId}/actions

returns entries describing what can be performed against the identified process instance. This includes whether or not an Ad-Hoc start event is possible. This is called "ACTION_INJECT_TOKEN". A further API can be called which can be used to start such an Ad-Hoc start event. This API is called:

POST /rest/bpm/wle/v1/process/{instanceId}?action=adhoc&step={stepName}

Working with REST Adhoc activities

Listing Adhoc activities

Given a process instance, we can ask that instance what ad hoc activities it may be harboring. The command for this is:

GET /rest/bpm/wle/v1/process/{*instanceId*}/adHocActivities

An example response from this call might be:

{
  "status": "200",
  "data": {
    "activities": [
      {
        "id": "2118.9aff4391-ec14-4051-becd-0917217d3f61",
        "name": "Task 2",
        "executionState": "READY",
        "activityType": "USER_TASK",
        "executionType": "MANUAL",
        "optionType": "OPTIONAL",
        "required": false,
        "repeatable": true,
        "startTime": null,
        "endTime": null,
        "hidden": false,
        "enablingDocumentID": null
      },
		...
    ]
  }
}
  • id – The identity of the activity. Starts with 2118.
  • executionState

READY – Ready to be started. WORKING – Already working. WAITING – An expression needs to be met before this can be started. …

  • activityType

USER_TASK …

  • executionType

*MANUAL – Must be manually started. AUTOMATIC – Is automatically started.

optionType

OPTIONAL – The activity is optional. REQUIRED – The activity is required.

A possible icon selection mechanism:

executionState optionType icon
READY REQUIRED
READY OPTIONAL
WAITING REQUIRED
WAITING OPTIONAL

Available actions for ad hoc activities

Once we know the identity of an adhoc activity, we can ask about what we can do with it. The request

GET /rest/bpm/wle/v1/activity/{activityId}/availableActions

will return us a description of what can be done:

{
	status: "200",
	data: {
		actions: [
			"ACTION_VIEW_ACTIVITY",
			"ACTION_START_ACTIVITY"
		]
	}
}

Starting an ad hoc activity

An Ad Hoc activity can be started with:

POST /rest/bpm/wle/v1/activity/{activityId}?action=ACTION\_START\_ACTIVITY

Working with REST Services

Amongst the primary concepts of IBPM is that of “Services”. Services are the parts of a process that are usually linked together. As an entity, services have their own set of REST APIs available for use.

Starting a service from REST

An API call is available to start a service. It is defined as:

POST /rest/bpm/wle/v1/service/{serviceModelId}?action=start...

The REST API expects an serviceModelId parameter which can be either the serviceModelId parameter from the service model ID or it may be of the form

"<project-shortname>@<service-name>"

The serviceModelId format is a BPM ID value that is of the form "1.xxxxx". This can be obtained from the "itemID" property of an exposed service.

The only types of service that can be started are "AJAX Service" or "Human Service". The identity of the caller can be found from the tw.system.user_loginName property.

The optional parameters to this REST call include:

createTask (Boolean) – Should a task be created in which this service runs?

parts (String) – Which response items should be returned. Values can be:

data all (default) none

params (String) – A JSON expression describing the input parameters

snapshotId (String) – The id of the snapshot to be used to start the service

callerTaskId (String) – The id of the task that is associated with starting this service

callerModelId

callerProcessId

callerModelBranchId

An example response for a heritage coach looks as follows:

{
	"status":"200",
	"data":{
		"serviceStatus":"coach",
		"key":"@42",
		"step":"Collect MDN",
		"data":{"allData":null},
		"coach":"<Form>...</Form>",
		"coachEvals":{},
		"actions":["ButtonGroup0_Button0"],
		"actionsMap":{"ButtonGroup0_Button0":"Submit"}
	}
}

For current (8.5.0.1) Human Services/Coaches we see:

{"status":"200","data":{"serviceStatus":"coachNG","key":"953","step":"Main Demo Screen","data":{},"actions":null}}

The values of serviceStatus seems to describe what the next step will be. Values seen include:

  • coach – We have reached a coach
  • end – The service has ended

Getting data from a Service

An API call is available to retrieve variable values from the running Service. The format of the call is:

GET /rest/bpm/wle/v1/service/{*instanceId*}?action=getData&field={*variableName*}

The variable name should be the full name as in tw.local.{varName}. Simply supplying the name of the variable by itself is not sufficient.

An example response looks as follows:

{
	status: "200",
	data:
	{
		result: "{"xyz":"XYZVal"}",
		resultMap:
		{
			xyz: "XYZVal"
		}
	}
}

|| |Note:

The following was written pre 7.5.1 and appears to no longer be true. It is being left here for just now pending more detailed analysis. Experiment and review what works and doesn't work to be sure what is and is not currently applicable …. Author.

Experience seems to also show that a call to Start a task is required before this API may be used. This is not adequately explained or understood (yet).|

Experience also seems to show that the ability to execute JavaScript from a REST call is required. To set this up, edit the 99Local.xml configuration file and change the following:

…
	<enable-javascript-execution>true</enable-javascript-execution>
</common>

Again it is not yet known why this has to be changed and there may be security implications.

Setting data into a Service

Data variable values can be changed inside the content of a running service. This will most likely be a Human Service step.

GET /rest/bpm/wle/v1/service/{*instanceId*}?action=setData&field={*variableName*}

Getting a Service Model using REST

An API is available the returns the model of a Service. This is the declaration of what the interface of the service looks like. The API looks as follows:

GET /rest/bpm/wle/v1/serviceModel/{serviceId}

The serviceId parameter defines the ID of the service to be queried. This can be either the UUID of the service or the service identifier supplied in the format of “<ProcessAppShortName>@<ServiceName>”. The UUID of a service can be obtained from the field serviceID in the details of a returned task. This can then be used to associate a task to a service that created it.

Field Description
header Header information
diagram A diagram of the model
dataModel Abstract meta data description of the data expected as input and returned from the service

Here is an example of returned data:

{
	status: "200",
	data:
	{
		header:
		{
			name: "HS1",
			UUID: "guid:56d35d2f221c8d0e:-5a405e30:134fcb20625:-7f8d"
		},
		diagram:
		{
			step:
			[
				{
					name: "End",
					x: 700,
					y: 100,
					type: "ExitPoint",
					ID: "ProcessItem.548c1796-57aa-4b5c-a287-3a8a31eb5df4"
				}
			]
		},

		dataModel:
		{
			properties:
			{
				v1:
				{
					isList: false,
					type: "BO1"
				},
				v2:
				{
					isList: false,
					type: "String"
				}
			},
			inputs:
			{
				v1:
				{
					type: "BO1",
					isList: false
				}
			},
			outputs:
			{
				v2:
				{
					type: "String",
					isList: false
				}
			},
			validation:
			{
				String:
				{
					type: "string",
					description: "String Type"
				},
				BO1:
				{
					properties:
					{
						a:
						{
							isList: false,
							type: "String"
						},
						b:
						{
							isList: false,
							type: "String"
						},
						c:
						{
							isList: false,
							type: "String"
						}
					},
					type: "object"
				}
			}
		}
	}
}

Let us now look at the description of the data model. The data model is not instance data. It is not associated with a specific instance of a service. Instead, the data model is the model of what is expected as inputs and outputs from the service. The data model needs some interpretation so let us slow down and try and define some terms.

First, let us define something called a field. A field has three attributes:

  • name – the name of the field
  • type – the data type of the field
  • isList – a boolean indicator that describes if this is a list (array)

A data model starts with three named containers called “properties”, “inputs” and “outputs”. Each of these are a set of fields.

So, effectively what we have is:

{
	properties:
	{
		fieldA, fieldB
	}
	inputs:
	{
		fieldA
	}
	outputs:
	{
		fieldB
	}
}

There is a fourth container within the the data model that is called “validation”. This container contains a set of data types. A data type consists of the following properties:

  • data type name – The name of the data type
  • type – The type of the data type. This appears to be one of the following:

string – A String data type object – A Business Object

  • properties – If the type of the data type is “object”, then the properties container will be present. This is a set of fields describing the content of the object.
{
	validation:
	{
		String:
		{
			type: "string",
			description: "String Type"
		},
		BO1:
		{
			properties:
			{
				a:
				{
					isList: false,
					type: "String"
				},
				b:
				{
					isList: false,
					type: "String"
				},
				c:
				{
					isList: false,
					type: "String"
				}
			},
			type: "object"
		}
	}
}

Working with Exposed Items

Getting Exposed Processes

The list of exposed processes can be retrieved with:

GET /rest/bpm/wle/v1/exposed/process

An example returned would be:

{
	status: "200",
	data:
	{
		exposedItemsList:
		[
			{
				ID: "2015.202"
				branchID: "2063.3321e2c8-3f9b-4240-84cd-918a120e00ee"
				branchName: "Main"
				display: "BPD2"
				itemID: "25.c23430e6-62fe-4794-9f02-4f840a19b2d7"
				itemReference: "/25.c23430e6-62fe-4794-9f02-4f840a19b2d7"
				processAppID: "2066.69fd9a5f-7e91-4d7f-a386-fcdd64f65209"
				snapshotCreatedOn: "2013-02-07T17:32:31Z"
				snapshotID: "2064.c6cf862c-9d56-4420-ab5b-478ebaed10e8"
				snapshotName: "2013-02-07-1"
				startURL: "/rest/bpm/wle/v1/process?action=start&bpdId=25.c23430e6-62fe-4794-9f02-4f840a19b2d7&processAppId=2066.69fd9a5f-7e91-4d7f-a386-fcdd64f65209"
				tip: true
				type: "process"
			},
		…
		]
	}
}

Within these records, the following need further explanation:

  • itemID – This is the GUID for the BPD model
  • processAppID – This is the GUID for the Process App that contains the exposed process.
  • snapshotID – This is the Snapshot ID within the Process App for the exposed process.
  • ID

Given the information returned from an exposed process, on occasion we wish to know which Process App the exposed process is contained within. We see that we get its GUID code (2066.xxx) but that doesn't tell us the name of the Process App. Using the API to retrieve a list of all Process Apps, we can then match for this processAppID GUID and find the details for that application.

Working with REST Users and Groups

Users and groups known to IBM BPM can be queried through REST APIs.

The first API we will look at returns a list of all users:

GET /rest/bpm/wle/v1/users[?filter={*string*}][&parts={*string*}]

The filter parameter provides a suffix matching capability. For example, if the filter were "abc" then the returned users would only include those that start with "abc" (if any). The parts parameter allows us to control how much data is returned. Options are:

  • all
  • memberships
  • none
{
	"status": "200",
	"data":
	{
		"users":
		[
			{
				"userID": 9,
				"userName": "admin",
				"fullName": "Administrator",
				"isDisabled": false,
				"primaryGroup": null,
				"emailAddress": null,
				"userPreferences":
				{
					"Locale": "en",
					"Alert On Assign And Run": "true"
				},
				"memberships":
				[
					"Debug",
					"tw_admins",
					"tw_authors",
					…
				]
			}
			…
		]
	}
}

A second REST API allows us to obtain the details of a specific named user:

GET /rest/bpm/wle/v1/user/{*userNameOrID*}[?parts={*string*}]

The userNameOrID parameter identifies the user to be returned. To retrieve details on the current user, supply "current" as the name of the user.

The parts parameter may be one of:

  • all
  • none
  • memberships

The response for the retrieval of information for a single user is the same as for a list of users but, of course, only one user is returned.

Included in this response is the list of attributes for the user. These are called "userPreferences" in the returned object. The userPreferences field is itself a JavaScript object where the property name is the name of the attribute and its value, the value of the attribute.

If one wishes to set the value of an attribute, the following REST API can be used:

POST /rest/bpm/wle/v1/user/{userNameOrId}?action=setPreference&key=\<name\>&value=\<value\>

Working with REST Process Apps

A list of available Process Apps can be retrieved with the following command:

GET /rest/bpm/wle/v1/processApps

From withing the REST API Tester, this command can be found in

Other > Retrieve Process Applications

A typical response looks like:

{
   status:"200",
   data:{
      processAppsList:[
         {
            shortName:"TWP",
            name:"Process Portal",
            description:"",
            lastModifiedBy:"Internal TW Admin user",
            defaultVersion:"Main",
            installedSnapshots:[
               {
                  name:"7.5.1",
                  acronym:"7.5.1",
                  active:false,
                  ID:"2064.a7b6c684-65c4-420e-b7be-0a504bba24c5"
               }
            ],
            ID:"2066.23d3ecec-6fdb-4033-9c57-e931aa13761f",
            lastModified_on:"2011-11-21T15:15:04Z"
         }
      ]
   }
}

Of high importance is the “ID” field. The ID field is a UUID for the Process App. In some APIs, this is called the projectId.

See also:

Working with REST Toolkits

A list of available Toolkits can be retrieved with the following commands:

GET /rest/bpm/wle/v1/toolkit

A typical response looks like:

{
   "status":"200",
   "data":{
      "processAppsList":[
         {
            "shortName":"EPTK785",
            "name":"IBM External Participant Support",
            "description":"SPARK External Participant Support",
            "richDescription":"<HTML><HEAD></HEAD><BODY>SPARK External Participant Support</BODY></HTML>",
            "lastModifiedBy":"Neil",
            "defaultVersion":"Main",
            "installedSnapshots":[
               {
                  "name":"1.0.2-EE",
                  "acronym":"1.0.2EE",
                  "active":false,
                  "createdOn":"2017-10-11T20:39:58Z",
                  "snapshotTip":false,
                  "branchID":"2063.07bd0ea4-1a9d-4fc4-8316-b99b0acbbd03",
                  "branchName":"Main",
                  "ID":"2064.e0072c3a-d8b4-44f4-8690-c4d7d550db84"
               },
               {
                  "name":"2017-11-11 0941CT",
                  "acronym":"2017111",
                  "active":false,
                  "createdOn":"2017-11-11T15:41:50Z",
                  "snapshotTip":true,
                  "branchID":"2063.07bd0ea4-1a9d-4fc4-8316-b99b0acbbd03",
                  "branchName":"Main",
                  "ID":"2064.a50cdc64-7b59-48d6-908f-cbed4339ce04"
               }
            ],
            "ID":"2066.c02e662f-85d9-4d25-920e-c8eb4f4ec235",
            "lastModified_on":"2017-11-11T15:45:31Z"
         }
      ]
   }
}

Working with REST and heritage process document attachments

A heritage capability exists in which documents can be attached or associated with process instances. The REST interface provides capabilities to add a new document, update an existing document or delete a document. Notice that there is no API to retrieve a document. To retrieve a document, a separate URL/REST request is available. The list of documents (if any) associated with a process instance can be retrieved by examining the details of a process instance. From this, the document id can be determined which is used as a key in other requests.

Documents as managed by IBPM can be of two types known as "file" and "url". For a "url" type attachment, what is saved is a URL where the data for the attachment can be found. For a "file" type attachment, the data itself is saved by IBPM with the process instance. The name "file" is probably a bad name as it is really "data".

A common use of document attachments is to have the end user select a file from their local file system and have that attached to the process instance against which they are working. This is typically performed through a browser with a file upload button. When using IBM's Portal and Coaches, this is a straight forward task as the Coach provides a file upload ability. When writing a custom UI component, things become a bit more problematic. Because of obvious browser security rules, a browser client application (one running the browser) is not allowed to see the content of a file. Instead, when a file upload is requested, it is sent to a Web Server using an HTTP FORM (POST) mechanism. If we were to desire our own File upload mechanism to attach a document to a process instance, to what would we then send the HTTP FORM request? The answer is that we ourselves would have to write such a function.

Heritage - Adding a document to a process instance using REST

A command is provided that looks as follows:

POST /rest/bpm/wle/v1/process/{processId}?action=addDocument&name={name}&docType={file|url}&{data=data|docUrl=url}

In this command, the following attributes are needed:

Parameter Description
processId The id of the process instance to which the document it to be attached.
docType A value of "file" or "url" indicating which of the the two possible types of attachment are to be used.
data If the docType is "file", then this defines the data to be supplied and used in the request.
docUrl If the docType is "url", then this defines the URL to be associated with the attached document.
name Name associated with the document

It is likely that this API will be used in the mode of sending a POST request with the parameters supplied in the body of the request.

Heritage – Getting a list of attached documents

Asking a process for its details returns a list of documents attached to it. The documents are attached in an array called "documents" which has the following structure:

{
	name: "dddd",
	type: "FILE",
	date: "2012-04-20T15:51:22Z",
	length: 6,
	ID: "103"
}

Working with REST Business Objects

We can retrieve the details of a Business Object if we know the internal business object ID and either the process application ID, the snapshot ID or the branch ID.

GET /rest/bpm/wle/v1/businessobject/{boId}?[processAppId=2066.*]...

A business object ID starts with "12.*". An example response contains:

{
   isComplex:
   type: // The name of the data type
   isShared:
   properties: [{
      name: // The name of the property of the data type
      typeClass: // The type of the property
      typeClassSnapshotId:
      typeClassBranchId:
      isArray:
   }]
}

If the property is a primitive, then the "typeClassRef" will be null. If it is a complex type, then the "typeClassRef" will be the boId and the typeClassBranchId will be the branchId value (2063.*).

Imagining a business object called Customer that contains three properties called "address", "name" and "age". If address is itself a Business Object we might see:

{
   "status":"200",
   "data":{
      "isComplex": true,
      "type": "Customer",
      "isShared": false,
      "iconType": 0,
      "name": "Customer"
      "properties":[
         {
            "typeClass": "Address",
            "typeClassRef": "12.d96dd2ee-01d6-4141-9413-53cd070f5472",
            "typeClassSnapshotId": null,
            "typeClassBranchId": "2063.b173967f-b114-448c-9d7c-68486761f627",
            "isArray": false,
            "name": "address"
         },
         {
            "typeClass": "Integer",
            "typeClassSnapshotId": null,
            "typeClassBranchId": null,
            "isArray": false,
            "name": "age"
         },
         {
            "typeClass": "String",
            "typeClassSnapshotId": null,
            "typeClassBranchId": null,
            "isArray":false,
            "name": "name"
         }
      ],
      "iconType": 0,
      "name": "Customer"
   }
}

Working with REST Asset Lists

This request retrieves a list of the assets in a Process Application that can be used to generate documentation. Examples of this API having been seen to be used include deriving the list of BPDs within a Process App.

GET /rest/bpm/wle/v1/assets?[processAppId=2066.*][&branchId=???][&snapshotId=???]

Categories:

  • Human Service – List of human services
  • Participant
  • Case
  • Coach Flow
  • VariableType – List of variable type definitions
  • BPD – List of BPDs
  • Project Defaults
{
   status: "200",
   data:
   {
      "Human Service":
      [
         {
            poId:
            poVersioId:
            tags: [],
            name:
            existsInTarget:
            sameVersionId:
            hasBrokenDep:
            isNewerVersion:
            shared:
            last_modified_by_userId:
            last_modified_by_userName:
            last_modified:
         }
         ...
      ],
      "Participant": []
      "VariableType": [{
         poId: "12.*"
         poVersionId:
         tags:
         existsInTarget:
         sameVersionId:
         isNewerVersion:
         shared:
         iconType:
         name:
         last_modified_by_userid:
         last_modified_by_userName:
         last_modified:
      }]
      "BPD": [{
         description:
         existsInTraget:
         hasBrokenDep:
         iconType:
         isNewerVersion:
         last_modified:
         last_modified_by_userId:
         last_modified_by_userName:
         name:
         poId: "25.xxx"
         poVersionId: UUID:
         richDescription:
         sameVersionId:
         shared:
         tags: []         
      }]
      "ProjectDefaults": [{
         poId: "63.*"
         poVersionId:
         tags:
         existsInTarget:
         sameVersionId:
         hasBrokenDep:
         isNewerVersion:
         shared:
         iconType:
         name:
         last_modified_by_userid:
         last_modified_by_userName:
         last_modified:
      }]
      snapshotId: "2064.*"
      snapshotCreationDate:
      snapshotName:
      branchId: "2063.*"
      branchName:
      projectId: "2066.*"
      projectName:
      isToolkit:
   }
}

Each entry in the categories is termed a “Persistence Object” and is composed of the following fields:

  • poId
  • poVersionId
  • tags
  • name
  • last_modified_by_userId
  • last_modified_by_userName
  • last_modified
  • description
  • richDescription
  • existsInTarget
  • sameVersionId
  • hasBrokenDep
  • isNewerVersion
  • shared

For example:

{
	"poId": "25.6d9998de-a414-4491-99e0-eae70490999c",
	"poVersionId": "90718ea4-b374-457d-b2dd-c2b7fe1a2957",
	"tags": [],
	"existsInTarget": false,
	"sameVersionId": false,
	"hasBrokenDep": false,
	"isNewerVersion": false,
	"shared": false,
	"name": "BPD1",
	"last_modified_by_userId": 1002,
	"last_modified_by_userName": "Neil",
	"last_modified": 1404100690321
},

In REST API Tester, we will find this entry under Process Documentation API → Assets.

See also:

Getting Project branchIds and Snapshots

There is an API called “Get Project Named Snapshots List Resource”. This is a mouthful. It takes as input the “ID” value of a Process App or Toolkit (what the REST API calls a Project ID). Process App Ids start with code "2066.xxx".

This API looks as follows:

GET /rest/bpm/wle/v1/project/{projectId}/snapshots

The projectId appears to be the ID field of a query of a Process App

What it returns looks like follows:

{
	status: "200",
	data:
	{
		branches:
		[
			{
				branchId: "2063.38158f45-7dc9-4293-bf55-e3176a4659ba",
				name: "Main",
				snapshots: 
				[
					{
						snapshotId: "2064.190135b9-9a63-4f1a-8cdb-94998b41916d",
						name: "Post Josh",
						desc: "",
						createdBy_userId: 9,
						createdBy_userName: "Administrator",
						created_on: 2147483647
					},
					{
						snapshotId: "2064.473163b7-f626-42b4-bb87-aa965d53efae",
						name: "v2.0",
						desc: "",
						createdBy_userId: 9,
						createdBy_userName: "Administrator",
						created_on: 2147483647
					}
				]
			}
		]
	}
}

Another API is GET /rest/bpm/wle/v1/project/{projectId}/branches

ane example of output from that looks like:

{
  "status":"200",
  "data":{
     "branches":[
        {
           "branchId":"2063.d14d6682-aa9b-4075-8cff-a81171bcf7d1",
           "name":"Main"
        }
     ]
  }
}

Notice that the response data contains the branchId entry. This is used extensively in other REST requests.

A question that may occur to you is “Where do I get the projectId from?”. The answer to this is that we can execute a command to retrieve a list of Process Apps. This is described Working with Process Apps. Process App Ids start with “2066.xxx”.

Getting Business Object definitions

The meta data description of a specific Business Object definition can be retrieved.

GET /rest/bpm/wle/v1/businessobject/{poId}?[branchId=...][snapshotId=...]

To obtain this detailed description , we need the “Persistence Object ID” of the Business Object that we wish to query. To obtain this we need to query the Asset List of a Process App or Toolkit. Remember, the Business Object is defined within that. In order to examine the Asset List of a Process App, we need the branchId of the Process App. That is itself a different REST call. When using that call we need to know the ID value of the Process App.

An example of a response looks like:

{
  "status": "200",
  "data": {
    "isComplex": true,
    "type": "BO1",
    "isShared": false,
    "properties": [
      {
        "typeClass": "String",
        "typeClassSnapshotId": null,
        "typeClassBranchId": null,
        "isArray": false,
        "name": "a"
      },
      {
        "typeClass": "BO2",
        "typeClassRef": "12.4ad5f41f-27c8-4c20-ad82-bd08c78ef529",
        "typeClassSnapshotId": "2064.0df8478f-e6aa-488d-9842-459ff6e1610f",
        "typeClassBranchId": null,
        "isArray": false,
        "name": "b"
      },
      {
        "typeClass": "String",
        "typeClassSnapshotId": null,
        "typeClassBranchId": null,
        "isArray": false,
        "name": "c"
      }
    ],
    "name": "BO1"
  }
}

See also:

Working with REST performance queries

As process instances execute, they can record timings of various states to the Performance Data Warehouse for subsequent analysis. Some of the REST requests provide access to this data.

GET /rest/bpm/wle/v1/performance/query?filter=bpd|<BPD ID>&filter=snapshot|<Snapshot ID>

The BPD ID is a BPD ID starting with 25.xxx and the Snapshot ID is the ID of the snapshot hosting the BPD. This Snapshot ID starts with 2064.xxx.

An additional query parameter is called "columns" which contains a list of the columns of data to be returned. These are comma separated values taken from the list of:

  • taskId – The ID of a task.
  • instanceId – The ID of the BPD instance
  • bpdName – The name of the BPD
  • taskSubject – The subject of the task
  • taskArrived – The time the task arrived
  • taskStarted – The time the task started
  • taskFinished – The number of milliseconds it took to run the task

An example response might be:

{
	"status":"200",
	"data": {
		"data":[
			{
				"taskId":"91",
				"instanceId":"2014-07-07T00:16:58Z",
				"bpdName":"AutoTrack1",
				"taskSubject":"Task 1",
				"taskFinished":35707,
				"taskArrived":"2014-07-07T00:17:10Z",
				"taskStarted":"2014-07-07T00:17:13Z"
			},
			{
				"taskId":"92",
				"instanceId":"2014-07-07T00:17:16Z",
				"bpdName":"AutoTrack1",
				"taskSubject":"Task 1",
				"taskFinished":35708,
				"taskArrived":"2014-07-07T00:21:37Z",
				"taskStarted":"2014-07-07T00:21:39Z"
			}
		],
		"rollupResult":null,
		"autoColumns":[]
	}
}

Working with REST system data

The BPM sever maintains meta data about its own configuration. We can retrieve that data using:

GET /rest/bpm/wle/v1/systems

what is returned is a JSON object that contains (for example):

{
  "status": "200",
  "data": {
    "systems": [
      {
        "systemID": "1efc26b9-a912-41d3-8117-41635b096977",
        "systemType": "SYSTEM_TYPE_WLE",
        "version": "8.6.0.0",
        "buildLevel": "BPM8600-20170918-081825",
        "groupWorkItemsEnabled": false,
        "substitutionEnabled": false,
        "substitutionManagementRestrictedToAdministrators": false,
        "taskHistoryEnabled": false,
        "workBasketsEnabled": false,
        "businessCategoriesEnabled": false,
        "taskSearchEnabled": true,
        "notificationWebMessagingEnabled": true,
        "taskListWebMessagingEnabled": true,
        "apiVersion": "1.0",
        "supports": null,
        "resources": [
          "tasks",
          "taskTemplates",
          "processes"
        ],
        "hostname": "workvm"
      }
    ]
  }
}

Working with REST retrieved diagrams

A number of the REST requests retrieve descriptions of diagrams back from the run-time. These can be used to visualize various parts of the solutions.

Process Visual Model

GET /rest/bpm/wle/v1/visual/processModel/<bpdId>?snapshotId or branchId or projectId

GET /rest/bpm/wle/v1/visual/processModel/instances?instanceIds=[<>]&bpdId=<>&snapshotId=<>

Make sure not to confuse this with

GET /rest/bpm/wle/v1/processModel which also returns diagram info but not enough to draw anything properly.

Return data

{
  status: "200",
  data:
  {
    name: {String}             // Name of the BPD
    poId: {String}             // BPD Id
    poVersionId: {String}
    identifier: {String}       // Name of property that is unique
    id: {String}               // A unique ID for this BPD element/step
    width: {Number}            // Width of the diagram
    height: {Number}           // Height of the diagram
    label: {String}	           // The label of the image
    items: [],
    links: [],
    properties: [],
    textPositions: [],
    activeTasks: [],           // May be present
    tokens:                    // May be present
  }
}

Now let us look at items. Items appear to be the visual “things” on the screen. The most important of these is the “items” array. Properties seen in them include:

{
  lane: {String}                // Swimlane that item lives in
  snapshotId:
  branchId:
  successors: [],
  preAssignment: {Boolean}
  postAssignment: {Boolean}
  conditional: {Boolean}
  eventActionType: {Number}
  interrupting: {Boolean}
  active: {Boolean}
  id: {String}                  // Unique id for this item
  label:                        // Text label
  x: {Number}                   // Left position
  y: {Number}                   // Top position
  type: {String}                // Type of item
  category: {String}
  colorIcon:
  bpmn2TaskType:
  poType:
  poId:
  attachedEvents:
  loopType:
  isSystem:
  color:
  width:
  height:
  children:
}

The core discriminator appears to be the property called “type”. Some of the values that we see associated with this include:

  • start
  • end
  • activity
  • swimlane

Here is a table of these properties and which exist in which type

Property start end activity swimlane
isSystem
color
width
height
children
id
label
x
y
type
category
snapshotId
branchId
successors
attachedEvents
preAssignment
postAssignment
conditional
eventActionType
interrupting
active
id
colorIcon
lane
bpmn2TaskType
poType
serviceType
poId

Type = start or end

{
  lane:
  snapshotId:
  branchId:
  succesors:
  attachedEvents:
  preAssignment:
  postAssignment:
  conditional:
  eventActionType:
  interrupting:
  active:
  id:
  label:
  x:
  y:
  type:
  category:
}

Type = activity

{
  colorIcon:
  lane:
  bpmn2TaskType:
  poType:
  serviceType:
  poId:
  snapshotId:
  branchId:
  succesors:
  attachedEvents:
  loopType:
  preAssignment:
  postAssignment:
  conditional:
  eventActionType:
  interrupting:
  active:
  id:
  label:
  x:
  y:
  type:
  category:
}

Type = swimlane

{
  isSystem:
  color:
  width:
  height:
  children:
  id:
  label:
  x:
  y:
  type:
}

For visualization of these, the important fields are:

  • id – This is a unique key to the item on the screen.
  • x, y – This is the X and Y coordinates of the item on the screen but relative to the swim lane. Unfortunately, these is once again more to this story than meets the eye. If we imagine a start icon, we might assume that the x,y is that of the top left as in:

however, if we click on the icon, we find that there is an invisible rectangle around it and the x,y of the icon is that of the invisible rectangle:

When drawing images, we then need to decide which "system" to use. If we wish to use the top left of the activities, then we will need offsets. In projects, we might call these "image offsets".

  • label – This is the label contained in the item. Experience seems to show that the label is already split using newline characters into logical lines. For example, if a line would be too wide for a visual item, it is split into newline parts.

  • type – This is the type of item on the screen. Types seen include:

    • start
    • end
    • activity
    • msgStartEventInterrupting
    • adhocStartEvent
    • messageEndEvent
    • errorEndEvent
    • terminate
    • intermedCatchMsgEventNonBoundary
    • intermediateThrowMsgEvent
    • intermedCatchTimerEventNonBoundary
    • intermedCatchTackingEventNonBoundary
    • gateway
    • gatewayAnd
    • gatewayOr
    • gatewayEvent
    • group
    • intermedCatchErrorEventBoundary
    • intermedCatchMsgEventBoundaryInterrupting
    • intermedCatchTimerEventBoundaryInterrupting
  • category – This is the category of the item

    • StartEvent
    • Activity
    • EndEvent

For type of "activity"

  • ServiceType – The type of activity
    • "Human Service"
    • "General System Service"
  • bpmn2TaskType – The type of activity
    • "ScriptTask"
    • "UserTask"
    • "DecisionTask"
    • "ServiceTask"
    • "SubProcess"
    • "CalledProcess"
    • "None"

Let us look for a moment at the (x,y) position of an item. Each item seems to have an (x,y) pair of attributes that describes where that item should be positioned on the screen. Unfortunately, it is not quite as easy as that. The (x,y) coordinates are relative to the swim-lane in which the item lives. There is a class of item of type “swimlane”. These items also have an (x,y) pair. For an arbitrary item that is to be displayed, we first need to find the swim-lane in which it lives and then add the (x,y) pair of the swim-lane to the (x,y) pair of the item to find the screen (x,y) pair. For an item to be drawn within a swimlane, that item has an attribute called "lane" which has a value of the label of the swimlane within which it is contained.

Another key area within this data is the “links” array. This is an array of “links” which are the wires connecting one item to another. This data structure contains:

{
  needDefaultMarker: {boolean} // If true a marker is needed on the line to show that this is the default path.
  needDiamondMarker:
  id:
  name:
  start: {id}         // The id of the start item
  startPosition:
  end: {id}           // The id of the end item
  endPosition:
  showName:
  showEndState:
  linkLabelPosition:
  gfx: {String}       // This appears to be a String of a JSON object that is an array of intermediate points
  inCriticalPath:
}

For visualization of these, the important fields are:

  • startPosition, endPosition – Where on the item does the line start or end. Entries here include:
    • rightCenter
    • rightBottom
    • rightTop
    • leftCenter
    • leftTop
    • leftBottom
    • bottomLeft
    • bottomCenter
    • bottomRight
    • topRight
    • topCenter
    • topLeft

We can see a pictorial representation of these offsets here:

2017-12-31.png

Now let us consider a start point of a single line. The line's point is identified by the id of the activity to which it is attached. This is a UUID. De-referencing that UUID we find an (x,y) pair and the type of activity that it represents. In the BPM model, each type of activity has geometric boundaries. We also find that the line has an attachment position (startPosition). What this all means is that the (x,y) position of the line in the screen will be:

x = functionX(activity.x, activityType, attachmentPosition)

and

y = functionY(activity.y, activityType, attachmentPosition)

for any given activityType and attachmentPosition, the values can be looked up through a constant mapping.

  • start, end – Ids for the Items representing the start and end objects
  • gfx – A string representation of a JSON object that is an array of points. The general format appears to be:
{
  intermediatePoints:
  [
  {
    x: {Integer},
    y: {Integer}
  }
  ]
}

But remember … the gfx field appears to be a String and not an expanded JSON object. It has also been found that if the start and ends of the links are in different swim lanes then an offset of 24 pixels must be added to the "x" coordinate of the intermediatePoints. It appears that this is most likely a bug but is now unlikely to be corrected because of the potential negative side effects to existing technologies. It also seems that if the start and end items are in different swimlanes then the intermediatePoints are in absolute coordinates but if the start and end items are in the SAME swimlanes then we need to add the "y" offset of the swimlane.

The core model for links is that each link identifies the item from which the link should start and the item to which the link should end. These items are identified in the link data by the fields “start” and “end”. These are uuids that correspond to the “id” field in the items.

So … what then is the algorithm for drawing a link from one item to another?

First, we look at the link.start value. This will reference the id of an item. Getting to that item, we then know the item.x and item.y position. Similarly, looking at the link.end value, we get to a second item and learn its item.x and item.y position.

A directory can be found on the server which contains icons for all the different aspects of the product as shown in Process Designer. The directory is:

C:\\IBM\\BPM\\v8.5\\profiles\\Node1Profile\\installedApps\\PCCell1\\IBM\_BPM\_WebPD\_SingleCluster.ear\\web-pd.war\\script\_rel\\com\\ibm\\bpm\\web\\process\\viewer\\view\\images\\BPD


\<Profile\>\\installedApps\\\<Cell\>\\IBM\_BPM\_Teamworks\_\<Node\_Server\>.ear\\webviewer.war\\widgets\\com\\ibm\\bpm\\wpd\\images\\BPD

Type Size
activity 95x70
start 24x24
gateway

A closer look at tokens

If the "tokens" property is present, it has the following structure:

"tokens":
{
  "bpdid:56d35d2f221c8d0e:-1ff5e133:13895e09ee1:-7fe6":
  [
  {
    "instanceId": "456",
    "createTime":"2012-07-19T04:28:15Z",
    "createTimeLong":1342672095246,
    "active":true,
    "tokenId":"2"
  }
  ]
}

Basically tokens is a list of items in the diagram keyed by bpdid.

The items within the diagram are joined together with lines. These are called "Links" within the REST returned JSON data. An example of a link looks as follows:

{
  "needDefaultMarker": false,
  "needDiamondMarker": false,
  "id": "bpdid:c546ae322ac77f8a:-79f454f0:1445fc8481a:-7fe0",
  "name": "to Receive Claim",
  "start": "bpdid:c546ae322ac77f8a:-79f454f0:1445fc8481a:-7ff4",
  "startPosition": "rightCenter",
  "end": "bpdid:c546ae322ac77f8a:-79f454f0:1445fc8481a:-7ff2",
  "endPosition": "leftCenter",
  "showName": false,
  "showEndState": false,
  "linkLabelPosition": 0.5,
  "gfx": "{\"intermediatePoints\":[]}",
  "inCriticalPath": false
}

The properties of this data need some explanation.

  • id – The identity of the link. Each link has its own identity.
  • start – The "item" that is the start of the link.
  • end – The "item" that is the end of the link.
  • startPosition – Where "upon" the start item should the link begin
  • endPosition – Where "upon" the end item should the link end

Swimlanes can contain an element called "children" which is an array of objects where each object has the form:

{
  _reference: "bpdid...."
}

Calling REST from Java

Although typically REST APIs are called from browser environments running JavaScript, there is absolutely nothing to prevent a Java client application from invoking REST directly. Here is an example application that makes a REST request. The core of the sample uses the Java supplied class HttpURLConnection. This class owns the ability to build and transmit correctly formatted HTTP requests. The sample also adds basic HTTP authentication data to ensure that the IBPM runtime knows the identity of the caller.

The response data is retrieved as a String. To use that data we will have to parse it as either a JSON data structure or an XML data structure depending upon the return type. It is strongly recommended to "play" with an individual REST call for a while before attempting to code up a solution. This will prepare you for understanding the data expected to be received by the runtime as well as the response sent back.

The HTTP security mechanism expects the userid and password to be Base64 encoded. Oddly, the Java 6 libraries don't appear to have a Base64 encoder supplied with them however the ApacheCommons "Codec" package which is available for free download provides just what is needed. The new Java 8 libraries do have a Base64 encoder.

package com.kolban.rest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class Main {
 public static void main(String args[]) {
  try {
   URL url = new URL("http://localhost:9080/rest/bpm/wle/v1/systems");
   HttpURLConnection httpUrlConnection = (HttpURLConnection)
   url.openConnection();
   String wasUserName = "admin";
   String wasPassword = "admin";
   String authorization = "Basic " + new
   String(org.apache.commons.codec.binary.Base64.encodeBase64(new String(wasUserName + ":" + wasPassword).getBytes()));
   // For Java 8
   // String authorization = "Basic " + Base64.getEncoder().encodeToString((new String(wasUserName + ":" + wasPassword).getBytes()));
   httpUrlConnection.setRequestProperty("Authorization", authorization);
   httpUrlConnection.setRequestMethod("GET");
   //httpUrlConnection.setDoOutput(true);
   //httpUrlConnection.setRequestProperty("content-type", "text/xml");
   /* * String data = "\<data to write\>";
   OutputStreamWriter wr = new\ * OutputStreamWriter(httpUrlConnection.getOutputStream());\ * wr.write(data);
   wr.flush();\ * /
   System.out.println("Response: " + httpUrlConnection.getResponseCode() + ": " + httpUrlConnection.getResponseMessage());
   InputStreamReader inReader = new
   InputStreamReader(httpUrlConnection.getInputStream());

   BufferedReader br = new BufferedReader(inReader);
   String line = br.readLine();
   while (line != null) {
    System.out.println("Line is: " + line);
    line = br.readLine();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

To take advantage of passing the context data from an authenticated application, the following Java code fragment can be added:

If the caller is running in an authenticated context, then an LTPA token can be passed. Adding the following before connecting to the server will achieve this:

Set s = WSSubject.getCallerSubject().getPublicCredentials(WSCredential.class);
WSCredential creds = (WSCredential) s.iterator().next();
byte token[] = creds.getCredentialToken();
httpUrlConnection.setRequestProperty("cookie", "LtpaToken=" + Base64.encode(token));

When using JSON from a Java environment, there are a few options. One can install the IBM freely distributed Feature Pack for Web 2.0 into the WAS server which will provide the com.ibm.json.java package or alternatively you can utilize the free open source package found at www.json.org. A more recent story is the JSR374 specificationfor Java native JSON processing. A reference implementation can be found on the Internet.

See also:

Using Apache HTTP Client

The Apache HTTP Client is one of the richest and most powerful libraries for working with REST calls from a Java environment available.

See also:

REST encoded UUIDs/GUIDs

Within the REST APIs, we appear to have a lot of “ids”. These appear to be long UUIDs. However, they seem to have encoding at their beginning that gives us an indication of their purpose. Here are some of the ones found so far:

Code Description
2015 Process/Task Template ID
2063 Branch ID
2064 Snapshot ID
2066 Process App ID
2072 Process Instance ID
2078 Task ID
1 Service Persistence Object
12 Variable Type Persistence Object aka (boId)
25 BPD/Case Persistence Object
60 External Activity ID
63 Project Defaults Persistence Object

We can convert a string that is encoded to one that is not encoded using:

value.replace(/\^2072\\./, "")

REST input and output data types

Processes and services can have input and output data. We can execute a query on a service or a process for the description of the data expected as input or returned as output. From this description, we can dynamically build an input structure. The format of the response of what input data looks like is interesting. Generically, it looks as follows:

DataModel:
 {
 properties: {object},
 inputs: {object},
 outputs: {object},
 validation: {object}
 }

The inputs object has a property for each of the inputs of the service. The outputs object has a property for each of the outputs. The properties object is extremely badly named and is in fact the "private" variables for the process or service. Each one of those properties is itself an JSON object that looks as follows:

{
 isList: boolean,
 type: string
 }

The name of the property corresponds to the name of the parameter of the service. Let us now focus a little more on the type field. The type field describes the data type of the parameter. This is where the validation property comes into play. The validation property is again an Object. Each of its properties corresponds to a type in the inputs and outputs objects. These objects have the following form:

Atomic data type:

{
 type: string,
 description: string,
 ID: string,
 richDescription: string
 }

Object data type:

{
 type: "**object**",
 ID: string,
 isShared: boolean,
 properties: \<A validation type\>
 }

REST Security

When a request is made to the BPM server using REST, the caller must be authenticated to permit the appropriate action. Since the REST request is arriving over HTTP, WAS based HTTP security applies. There are a number of ways that authentication may be achieved. The first is the use of the technique called basic HTTP authentication. This means sending a userid/password pair with each request. Although this works, it is not the best nor most secure mechanism. With basic HTTP authentication, the password is passed in a simple Base 64 encoding which means that it is trivially de-codable. If basic authentication is chosen, then it is recommended to send the HTTP requests using SSL transport security to ensure that the content can not be examined. Instead of using basic authentication, LTPA tokens can be utilized. The concept here is that a user authenticates with the WAS server once and a token (a large string of characters) is returned. That token is then passed back from the browser with each subsequent REST request. Since the token was generated by WAS and is known only to the browser that performed the initial login, this token is trusted by WAS and allows WAS to know the caller's identity based on the previous successful login that generated the token. The token is passed back implicitly to the WAS server through a browser held cookie.

To perform a login to WAS, the following simple web page can be used. This page is called "login.html".

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login</title>
</head>
<body>
	<h2>Form Login</h2>
	<FORM METHOD=POST ACTION="j_security_check">
		<p>
			<font size="2"> <strong> Enter user ID and password:
			</strong>
			</font> <BR> <strong> User ID</strong> <input type="text" size="20"
				name="j_username"> <strong> Password </strong> <input
				type="password" size="20" name="j_password"> <BR> <BR>
			<font size="2"> <strong> And then click this button:
			</strong>
			</font> <input type="submit" name="login" value="Login">
		</p>
	</form>
</body>
</html>

When displayed, it looks as follows:

If the user fails to authenticate, a second page is needed to show an error. This file is called "error.html":

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<H1>A Form login authentication failure occurred</H1>
	<P>Authentication may fail for one of many reasons. Some
		possibilities include:
	<OL>
		<LI>The user-id or password may be entered incorrectly; either
			misspelled or the wrong case was used.
		<LI>The user-id or password does not exist, has expired, or has
			been disabled.
	</OL>
</body>
</html>

The final step is to update the Java EE WAR deployment descriptor to state that "FORM" based security is to be used to authenticate the user:

<login-config>
	<auth-method>FORM</auth-method>
	<realm-name>MYREALM</realm-name>
	<form-login-config>
		<form-login-page>/login.html</form-login-page>
		<form-error-page>/error.html</form-error-page>
	</form-login-config>
</login-config>

Should we wish to use basic auth, we must add a header to the HTTP request that conforms to the basic auth specification. At the highest level, we add a header that contains:

Authorization: Basic userid:password

where the string "userid:password" is base 64 encoded.

In Javascript, we might thus code:

var userid      = "kolban";
var password    = "password";
var headerName  = "Authorization";
var headerValue = "Basic " + btoa(userid + ":" + password);
// Set the header with headerName and headerValue

See also:

The 8.5.7 REST interface

With the arrival of 8.5.7 and the cumulative fixes on top of it, a revamped REST interface was developed. This also comes with an Open API specification of the services. We can review the definitions by pointing a browser to:

https://<host>:<port>/bpm/explorer

The underlying Open API specification can be retrieved from:

http://<server>:<port>/bpm/docs

REST – System

REST – Process

REST – User Task


Revision #5
Created 1 year ago by Admin
Updated 1 year ago by Neil Kolban