The previous post describes some basic principles related to task management in the Nova Bonita BPM platform. Hook execution, the life cycle of the tasks and the API calls necessary to manage them where among the items discussed.
A minimal application that applies those principles is provided and discussed in this post. This Java class can be compiled and run as is. Information on how build the application and set up the persistence environment can be found on previous posts. Please note some posts were written for previous versions of the Bonita platform. You will need to adjust the instructions to accommodate the changes introduced by newer versions.
Full Code
package org.bonitaworld;
import java.util.Iterator;
import javax.security.auth.login.*;
import org.ow2.bonita.facade.*;
import org.ow2.bonita.facade.exception.*;
import org.ow2.bonita.facade.runtime.*;
import org.ow2.bonita.facade.uuid.*;
import org.ow2.bonita.util.*;
public class TaskExecutionExample {
public static void main(String[] arguments)
throws LoginException,
TaskNotFoundException,
IllegalTaskStateException,
ActivityNotFoundException,
VariableNotFoundException{
TaskUUID taskUUID;
String whatAction;
LoginContext loginContext;
ActivityInstance currentActivity;
loginContext =
new LoginContext("Bonita",
new SimpleCallbackHandler("john", "bpm"));
loginContext.login();
RuntimeAPI runtimeAPI = AccessorUtil.getRuntimeAPI();
QueryRuntimeAPI queryRuntimeAPI = AccessorUtil.getQueryRuntimeAPI();
Iterator<ActivityInstance<TaskInstance>> myIterator =
queryRuntimeAPI.getTaskList(ActivityState.READY).iterator();
while (myIterator.hasNext()){
currentActivity = myIterator.next();
taskUUID = currentActivity.getBody().getUUID();
runtimeAPI.startTask(taskUUID, true);
whatAction =
(String)queryRuntimeAPI.getVariable(currentActivity.getUUID(),
"Action");
if (whatAction.compareTo("SUSPEND") == 0){
runtimeAPI.suspendTask(taskUUID, true);
}else {
runtimeAPI.setVariable(currentActivity.getUUID(),
"Action",
"SUSPEND");
runtimeAPI.finishTask(taskUUID, true);
}
}
loginContext.logout();
}
}
Line by Line Explanation
public static void main(String[] arguments) throws LoginException, TaskNotFoundException, IllegalTaskStateException, ActivityNotFoundException, VariableNotFoundException
Exceptions are not properly managed in this example to reduce the complexity. In production applications, each kind of exception must be managed with try/catch blocks at the points where they are originated.
loginContext = new LoginContext("Bonita", new SimpleCallbackHandler("john", "bpm"));
loginContext.login();
The default identity service included in the Bonita Platform distribution requires the applications to log in using the JAAS standard API. This sample application uses a very simple login module provided with the distribution, and the JAAS configuration file jaas-standard.cfg, located in the bonita-runtime-4.1.1/conf folder.
RuntimeAPI runtimeAPI = AccessorUtil.getRuntimeAPI();
This code provides the programmer with access to the Runtime API
QueryRuntimeAPI queryRuntimeAPI = AccessorUtil.getQueryRuntimeAPI();
This code provides the programmer with access to the Query Runtime API
Iterator<ActivityInstance<TaskInstance>> myIterator = queryRuntimeAPI.getTaskList(ActivityState.READY).iterator();
The getTaskList(ActivityState.READY) returns all the activities assigned to the currently logged in user that are in READY status. This function can be used to get a list of activities in any other status or assigned to different users if that is necessary. The method returns a java.util.Collection with elements of ActivityInstance type. This instruction directly retrieves the java.util.Iterator to process the tasks, but any other manipulation of the Collection object is allowed. All activities in this list were processed previously by the BPM engine. That preprocessing included the execution of the OnReady hook, the Role Mapper and the Performer Assigner.
taskUUID = currentActivity.getBody().getUUID();
Tasks are the body of manual activities in the Bonita API. This function retrieves the UUID (Universal Unique IDentifier) of the task. This object is necessary to manage the task's life cycle.
runtimeAPI.startTask(taskUUID, true);
The startTask() function signals to the Bonita Engine that it needs to move a task from the READY status to the EXECUTING one. This allows the system to know when a user started to work on one of the items on his/her TODO list. As part of this function call, the engine executes the OnStart hook.
whatAction = (String)queryRuntimeAPI.getVariable(currentActivity.getUUID(), "Action");
One important function that allows the communication between front-end applications and the instances of the business processes managed by the Bonita Engine is the retrieval of variable values. The getVariable() method implements that function. In this case the value of a variable called Action is retrieved to take business decisions later on.
if (whatAction.compareTo("SUSPEND") == 0){
This code makes use of a process variable value to instruct the application regarding the business logic to execute. In the case of this example, if the Action variable has the value SUSPEND, the task will be suspended. Otherwise, the task will be normally finished and the engine will move the process to the next activities.
runtimeAPI.suspendTask(taskUUID, true);
The suspendTask() function changes the status of the task refered with with UUID from EXECUTING to SUSPENDED. It will triger the execution of the OnSuspend hook as well.
runtimeAPI.setVariable(currentActivity.getUUID(), "Action", "SUSPEND");
The setVariable() function is the partner of QueryRuntimeAPI.getVariable(). It allows the front end application to change the value of the process and instance variables. It receives the UUID of the activity where the variable value is going to be updated, the variable name and the value to store.
runtimeAPI.finishTask(taskUUID, true);
Once the application users complete a human activity (task) the BPM engine needs to be notified. The finishTask() method allows the applications to do that. It moves the status of the provided task from the EXECUTING to the FINISHED status and it triggers the execution of the OnFinish hook. Additionally, it's during the execution of this method that the workflow engine works to determine the following activities to execute. Once it has reached the next manual activities, it creates the corresponding tasks, executes their Role Mappers, Performer Assigners and OnReady hooks.