2016/10/10

Case management - jBPM v7 - Part 1

This article starts a new series of blog posts about case management feature that is coming in jBPM v7 to illustrate its capabilities with complete examples that will get more complex/advanced on each part.

One of the most frequently requested features in jBPM is so called Case Management. Case management can mean different things depending who you talked to so I'd like to start with small scope definition what does it mean in context of jBPM (at the moment as that might change based on feedback, supported features and use cases and further evolution).

Case management can be best described when compared to business processes. Business processes are usually modeled as flow charts with clearly defined paths to reach a business goal. These processes usually have one (might have more) starting points and are structurally connected to build end to end flow of work and data.



While cases are more dynamic, they provide room for improvements as the case evolve without the need to foresee all possible actions in advance. So case definition usually consists of loosely coupled process fragments that can be connected (directly on indirectly) to lead to certain milestones and finally business goal.

Looking at different notations that can be used for case management, processes and cases might be represented differently:

  • BPMN2
  • CMMN
jBPM comes with cases support based on BPMN2 as most users are familiar with this notation and most if not all features can be represented with BPMN2 constructs. That's at least a starting point which might be revisited further on. A good comparison between BPMN2 and CMMN was published by Bruce Silver.

These article series will introduce readers to case management support gradually with more features as we go to not provide too much details at once and let the features described be backed with examples that can be seen (screencast) and executed on the actual environment with jBPM v7.

Case project

First thing to start with, is to create Case project - it's a special type of project in KIE workbench that is on top of regular project to configure it for the case management:
  • set runtime strategy to Per Case
  • configure marshallers for case file and documents
  • create WorkDefinition.wid files in the project and its packages to ensure case related nodes (e.g. Milestone) are available in palette 


Case definition

So let's start with basic case definition example that covers following use case - IT hardware orders. As in any company, there is a need from time to time to order new IT equipment - such as computers, phones, etc. This kind of system can be represented with a good case management as they usually deal with a bit of dynamic decisions that might influence the flow. 

Case definition is created in authoring perspective in KIE workbench - it expects name, location and optionally case ID prefix. What's that? Case ID prefix is configurable element that allows to easily distinguish different types of cases. Default mechanism is that the prefix is then followed with generated id in following format:

ID-XXXXXXXXXX

where X is generated number to produce unique id with the prefix. If prefix is not given it defaults to CASE and then each subsequent instance of that case definition will be:
CASE-0000000001
CASE-0000000002
CASE-0000000003

or when prefix is set to HR
HR-0000000001
HR-0000000002
HR-0000000003

Case definition is always an adhoc process definition meaning it is a dynamic process so does not require to have explicit start nodes.

Once the clean definition is created, it's time to define roles involved in the usual case of ordering new IT hardware:
  • owner - is the person who requests the hardware (can be only one)
  • manager - is direct manager of the owner to approve the requested hardware
  • supplier - set of people that can order and deliver physical equipment (usually more than one)
When the roles are known, case management must ensure that these are not hardcoded to single set of people/groups as part of case definition and that it can differ per each case instance. This is where case role assignments come into the picture and can be:
  • given when case starts
  • set at any given point in time while case is active
  • removed at any given point in time while case is active
second and third option does not alter the task assignments for already active tasks.

What is important to note here, is that in case management users should always use roles for task assignments instead of actual user/group names, that is to make the case as dynamic as possible so actual user/group assignment is done as late as possible. It's similar to process variables though without expression syntax (#{variable}).

Let's take a look at our case definition:


So what do we have here? First thing that is directly seen is - no start nodes of the process. Does that mean there is no way to tell what is going to be triggered when new instance of this case definition is created?
Quite the opposite - nodes that have no incoming connections and are marked as Adhoc Autostart (a property of a node) will be automatically triggered when instance is started.

In this case these are:
  • Prepare hardware spec
  • Milestone 1: Order placed
Both of these nodes are wait states, meaning they are triggered but they are not left, they wait for further action:
  • Prepare hardware spec - wait for supplier to provide the spec and complete the task
  • Milestone 1: Order placed - wait for condition to be met - there is a case file variable named "ordered" with value true
Hmmm, but what is a case file then? Case File is like a bucket for data for entire case instance. Since case can span across number of process instances, instead of coping data back and forth (that first of all might be expensive and second can lead to use of out of date information) process instance can write and read from case file that is accessible to all process instance that belong to the same case. CaseFile is stored in working memory and thus is persiteable same as ksession and process instance - meaning can use marshaling strategies to store in different places e.g. documents, JPA entities etc. Though what's more important - it is a fact in working memory and thus can be subject for rules.

Milestone actually uses case file as condition to trigger only if there is a ordered variable available in case file and its value is true. Only then milestone will be completed and will follow to next node.

Another worth noting part is the end signals that are at the end of Milestone 1 and Milestone 2 fragments. These signals are responsible for triggering next Milestone in line, but again, only triggering and not completing it as they will wait on condition. The scope of signal is process instance only so completing Milestone 1 in first case instance will not cause any side effects on other active case instances of the same definition.

Here is a complete design of this project and case definition as screencast.





Complete source code of this project (and the entire repository) can be found here. This repository can be cloned directly to workbench for build and deploy.

... speaking of build and deploy....

The project can be directly build and deploy in workbench and (assuming you have KIE Server connected to workbench) provisioned to execution environment where it can be started and worked on.

At the moment workbench does not provide any case management UI, thus we will use REST calls to start a case and put data into case file but we can use workbench for user task interaction and overall monitoring - process instance logs, process instance image, active nodes, etc.

Start new case

To start a new case use following endpoint:
Endpoint::
http://host:port/kie-server/services/rest/server/containers/itorders/cases/itorders.orderhardware/instances

where

  • itorders is the container alias that was deployed to KIE Server
  • itorders.orderhardware is case definition id
As described above, at the time when new case is started it should provide basic configuration - role assignments:

POST body::
{
  "case-data" : {  },
  "case-user-assignments" : {
    "owner" : "maciek",
    "manager" : "maciek"
  },
  "case-group-assignments" : {
    "supplier" : "IT"
 }
}

At the moment case-data is empty as we don't supply any data/information to the case. But we do configure our defined roles. Two of them are user assignments (as can be seen in the above screen cast they are referenced in Actor property of user tasks) and third is group assignments (as it is referenced in Groups property of user task).

Once successfully stared it will return case ID that should look like
IT-0000000001

Then this case can already be seen in process instance list in workbench, and its tasks should be available in task perspective. So the tasks can be completed and various milestones will be achieved until it reaches the Milestone that requires shipped variable to be present in case file.

Insert case file data

Case file data can be easily inserted into active case using REST api.
Endpoint::
http://host:port/kie-server/services/rest/server/containers/itorders/cases/instances/IT-0000000001/caseFile/shipped

where
  • itorders is the container alias that was deployed to KIE Server
  • IT-0000000001 is the unique id of a case instance
  • shipped is the name of the case file variable to be set/replaced
POST body::
true

Same should be later repeated to insert "delivered" case file variable to achieve Milestone 3 and move to final task - Customer Satisfaction Survey. And that's all for this basic case example.

Execution in action can be found in this screencast



Comments and ideas more than welcome. And in addition, contribution to what cases should be provided as example are wanted!