In the first article in this series, Designing an event-driven business process at scale: A health management example, Part 1, we began by defining the business use case and data model for a concrete example from the health management industry. We then began implementing the example in jBPM (an open source business automation suite) by creating our trigger process.
Now, in the second article in this series, we will focus on creating the Task subprocess and its many components. In our case, these are:
- The Expired? gate
- The Suppressed? gate
- The human task
- The Reminder subprocess
- The "What type of close?" gate
- The Hard Close embedded subprocess
- The Escalation subprocess
The Task subprocess
Now you can create the Task subprocess with the properties shown in Figure 1.
Figure 1: Create the Task subprocess.">
The Task subprocess needs the variables shown in Figure 2 to be defined.
Figure 2: Define the variables for your Task subprocess.">
Note: The type com.jbpm.document.Document
of the variable sSupplementalData
is available out of the box.
Now, draw the diagram for the Task subprocess, as shown in Figure 3.
Figure 3: Create your Task subprocess diagram.">
Once the process variables are initialized in a script task, a user task must be completed. A reminder is set for the completion of the user task and an escalation is defined. Both the reminder and the escalation are implemented with timers that lead to subprocesses that you need to implement. See below for a note concerning timers from a scalability perspective.
Note: We implemented the task suppression requirement using a timer as well.
The hard close requirement is realized as an embedded subprocess that is simply catching a signal. Following the requirements, the escalation occurs due to a timer on this subprocess.
The Expired? gate
The Expired? exclusive gate should have two branches configured using the expirationDate
attribute of the Task class, as shown in Figure 4.
Figure 4: Checking if the task is expired.">
To configure the Yes branch, set up the condition expressions shown in Figure 5.
Figure 5: Defining the behavior if your task is expired.">
The Suppressed? gate
The Suppressed? exclusive gate's two branches should be configured using the suppressed
boolean attribute of the Task class, as shown in Figure 6.
Figure 6: Defining behavior depending on whether or not your task needs to be suppressed.">
Figure 7 shows the configuration for the Yes branch.
Figure 7: Entering the Yes branch.">
The suppression of the task is accomplished by a timer. The timer causes the process to wait for the period specified in the Task object's suppressionPeriod
attribute, as shown in Figure 8.
Figure 8: Defining the suppression timer.">
The human task
Now, let's focus on the human task, as shown in Figure 9.
Figure 9: Defining the human task.">
Configure the human task using the settings shown in Figure 10.
Figure 10: Implementing the human (actor) task.">
The task actor is resolved from the task actor assignment process variable.
Next, there are a couple of abilities you will want: To capture text as well as supplemental uploaded documentation and to complete the task with a Not Applicable or Not Available response. These requirements can be satisfied by configuring the task parameters as you see in Figure 11.
Figure 11: Defining the task's parameters to capture the types of data you need.">
You also need to satisfy the requirement of sending a periodic reminder to the task actor. There is a built-in notification capability in jBPM that allows sending email to notify groups and individuals to complete a task. For example, you could configure notifications for the Task activity as you see in Figure 12.
In many cases, the built-in notification capability may be adequate. However, there are cases where one would need more control over the notification process. The advantage of using timers for this purpose allows you to design as complex a reminder process as you want. In this example, you will implement timer-based reminders.Configure the timer on the task border, which will trigger the first reminder after the period of time defined in the reminderInitiation
attribute of the Task
object as shown in Figure 13.
The Reminder subprocess
Now you should configure the subprocess Reminder
, as shown in Figure 14. Notice that both the properties "Independent" and "Abort Parent" must be left unchecked while "Wait for Completion" is checked. If you don't configure it in this way the Reminder subprocess will not stop as it should.
Set the subprocess parameters to be the Reminder
and Task
objects, as shown in Figure 15.
After completion of the task, a signal should be sent to stop the reminder subprocess, as shown in Figure 16.
Figure 16: Creating the stop signal.">The "What type of close?" gate
An exclusive gate decides if the task close state should be soft or hard. The soft close branch of the gate looks like what you see in Figure 17.
Figure 17: Configuring the soft-close branch.">And the hard-close branch is shown in Figure 18.
Figure 18: Configuring the hard-close branch.">The Hard Close embedded subprocess
If the task close is hard, the process must wait for a confirmation signal coming from an external system. You have to configure this in an embedded subprocess because of the escalation requirement.
This subprocess is simple. There is just an intermediate signal catch, as shown in Figure 19.
Figure 19: Catching the signal for a hard close.">You also need to implement an escalation subprocess if the task is not closed in a given time. Again, jBPM has a built-in capability to reassign a task if it is not completed in a timely fashion. For example, you could configure how to reassign the task as you see in Figure 20.
Figure 20: Escalating (reassigning) a task that wasn't completed in a timely fashion.">However, you need to base the reassignment after receiving confirmation from an external system that the task was closed. Moreover, the period must be configurable as a variable, because this value depends on the specific task. Because of these reasons, you need to implement the escalation as a timer-triggered subprocess.
A border timer determines when an escalation is needed based on the value of the escalationTimer
attribute of the Task
object, as shown in Figure 21.
There is yet another way to implement SLA escalations. The ProcessEventListener
interface has two methods that capture the event of an SLA violation and can be implemented with custom code specifying what to do in such an event, as you can see in this example implementation:
/** * @param event */ public void beforeSLAViolated(SLAViolatedEvent event) { System.out.println( "Process <<"+ event.getProcessInstance().getProcessName()+ ">>-<"+ event.getProcessInstance().getId()+ "> ->SLA <<"+ event.getNodeInstance().getNodeName()+">>-<"+ event.getNodeInstance().getNodeId()+">-<"+ event.getNodeInstance().getId()+ "> SLA is about to be violated." ); } /** * @param event */ public void afterSLAViolated(SLAViolatedEvent event) { System.out.println( "Process <<"+ event.getProcessInstance().getProcessName()+ ">>-<"+ event.getProcessInstance().getId()+ "> ->SLA <<"+ event.getNodeInstance().getNodeName()+">>-<"+ event.getNodeInstance().getNodeId()+">-<"+ event.getNodeInstance().getId()+ "> SLA has been violated." ); }
The Escalation subprocess
Now, configure the Escalation subprocess, as shown in Figure 22.
Figure 22: Creating the Escalation subprocess.">Then define the parameters of the subprocess. You need to pass the Task
and the TaskActorAssignment
objects, as you can see in Figure 23.
Conclusion
So far in this series, we have defined the business use case for our health management event-driven business process, and have created our data model, trigger process, and task subprocess with all of its components. In the next installment, we will complete our example configuration.