2016/10/25

Case management - jBPM v7 - Part 3 - dynamic activities

It's time for next article in "Case Management" series, this time let's look at dynamic activities that can be added to a case on runtime. Dynamic means process definition that is behind a case has no such node/activity defined and thus cannot be simply signaled as it was done for some of the activities in previous articles (Part 1 and Part 2).

So what can be added to a case as dynamic activity?

  • user task
  • service task - which is pretty much any type of service task that is implemented as work item 
  • sub process - reusable

User and service tasks are quite simple and easy to understand, they are just added to case instance and immediately executed. Depending of the nature of the task, it might start and wait for completion (user task) or it might directly finish after execution (service tasks). Although most of the service tasks (as defined in BPMN2 spec - Service Task) will be invoked synchronously it might be configured to run in background or even wait for external signal to be completed - all depends on the implementation of the work item handler.
Sub process is slightly different in the expectations process engine will have - process definition that is going to be created as dynamic process must exists in kjar. That is to make sure process engine can find that process by its id to execute it. There are no restriction on what the subprocess will do, it can be synchronous without wait states or it can include user tasks or other subprocesses. Moreover such created subprocess will have correlation key set with first property being the case id of the case where the dynamic task was created. So from case management point of view it will belong to that case and thus see all case data (from case file - see more details about case file in Part 2).

Create dynamic user task

To create dynamic user task there are few things that must be given:
  • task name
  • task description (optional though recommended to be used)
  • actors - list of comma separated actors to assign the task, can refer to case roles for dynamic resolving 
  • groups - same as for action but referring to groups, again can use case roles
  • input data - task inputs to be available to task actors
Dynamic user task can be created via following endpoint:

Endpoint::
http://host:port/kie-server/services/rest/server/containers/itorders/cases/instances/IT-0000000001/tasks

where 
  • itorders is container id
  • IT-0000000001 is case id
Method::
POST

Body::
{
 "name" : "RequestManagerApproval",
 "data" : {
  "reason" : "Fixed hardware spec",
  "caseFile_hwSpec" : "#{caseFile_hwSpec}"
  }, 
 "description" : "Ask for manager approval again",
 "actors" : "manager",
 "groups" : "" 
}

this will then create new user task associated with case IT-000000001 and the task will be assigned to person who was assigned to case role named manager. This task will then have two input variables:
  • reason
  • caseFile_hwSpec - it's defined as expression to allow runtime capturing of process/case data
There might be a form defined to provide user friendly UI for the task which will be then looked up by task name - in this case it's RequestManagerApproval (and the form file name should be RequestManagerApproval-taskform.form in kjar).

Create dynamic service task

Service tasks are slightly less complex from the general point of view, though they might need more data to be provided to properly perform the execution. Service tasks require following things to be given:
  • name - name of the activity
  • nodeType - type of a node that will be then used to find the work item handler
  • data - map of data to properly deal with execution
Service task can be created with the same endpoint as user task with difference in the body payload.
Endpoint::
http://host:port/kie-server/services/rest/server/containers/itorders/cases/instances/IT-0000000001/tasks

where 
  • itorders is container id
  • IT-0000000001 is case id
Method::
POST

Body::
{
 "name" : "InvokeService",
 "data" : {
  "Parameter" : "Fixed hardware spec",
  "Interface" : "org.jbpm.demo.itorders.services.ITOrderService",
  "Operation" : "printMessage",
  "ParameterType" : "java.lang.String"
  }, 
 "nodeType" : "Service Task"
}

In this example, an java based service is executed. It consists of an interface that is a public class org.jbpm.demo.itorders.services.ITOrderService, public printMessage method with single argument of type String. Upon execution Parameter value is passed to the method for execution.

Number and names, types of data given to create service tasks completely depends on the implementation of service task's handler. In this example org.jbpm.process.workitem.bpmn2.ServiceTaskHandler was used.

NOTE: For any custom service tasks, make sure handler is registered in deployment descriptor in WorkItem Handler section where the name is same as nodeType used when creating a dynamic service task.

Create dynamic subprocess

Dynamic subprocess expects only optional data to be provided, there are no special parameters as for tasks so it's quite straight forward to be created. 

Endpoint::
http://host:port/kie-server/services/rest/server/containers/itorders/cases/instances/IT-0000000001/processes/itorders-data.place-order

where 
  • itorders is container id
  • IT-0000000001 is case id
  • itorders-data.place-order is the process id of the process to be created
Method::
POST

Body::
{
 "any-name" : "any-value"
}

Mapping of output data

Typically when dealing with regular tasks or subprocesses to map output data, users define data output associations to instruct the engine on what output of the source (task or sub process instance) to be mapped to what process instance variable. Since dynamic tasks do not have data output definition there is only one way to put output from task/subprocess to the process instance - by name. This means the name of the returned output of a task must match by name process variable to be mapped. Otherwise it will ignore that output, why is that? It's to safe guard case/process instance of putting unrelated variables and thus only expected information will be propagated back to case/process instance.

Look at this in action

As usual, there are screen casts to illustrate this in action. First comes the authoring part that shows:
  • creation of additional form to visualize dynamic task for requesting manager approval
  • simple java service to be invoked by dynamic service task
  • declaration of service task handler in deployment descriptor


Next, it is shown how it actually works in runtime environment (kie server)




Complete project that can be imported and executed can be found in github.

So that concludes part 3 of case management in jBPM 7. Comments and ideas more than welcome. And that's still not all that is coming :)