jBPM tasks
173Developing with the task AP
query = jbpmContext.getSession() .createQuery(queryText.toString()); List<ProcessInstance> processInstanceList = (List<ProcessInstance>) query.list(); return processInstanceList; }
This new method, listProcessInstances, requires three parameters. The first is JbpmContext, which as you saw in the previous example, represents a connection to the jBPM instance being used. The second parameter is processId, which is the unique process identifier associated with all jBPM processes (the listProcesses method in listing 6.2 returns such an ID for each process). The third value is the filter criteria, which can be either ENDED, RUNNING, or SUSPENDED. The second and third parameters will be used to construct the Hibernate query.
NOTE For those unfamiliar with Hibernate, it uses its own query language, which is similar but not identical to SQL.
The method logic begins by defining a Hibernate Query object
b
. This will be used for creating and executing the Hibernate query. The query statement is defined by building a StringBuffer called queryText that will contain the generated query state- mentc
. The statement is built dynamicallyd
ande
. Once completed, the Query object (query) is populated with the generated SQL statementf
, and then its list method called to return a List of resultsg
. The resulting List, which is cast to ProcessInstance’s, is returned by the methodh
.Listing 6.5 shows a fragment of a Java main() class (in the code samples, the class name is MainProcessInstances) that utilizes this new helper method.
public static void main(String[] args) { if (args.length != 2) {
System.out.println("Syntax is: MainProcessInstances <processId>" + "<one of RUNNING | ENDED | SUSPENDED>");
System.exit(1); } JbpmContext jbpmContext = JBPMHelper.getConfiguration().createJbpmContext(); List<ProcessInstance> processInstanceList; processInstanceList = JBPMHelper.listProcessInstances (Integer.parseInt(args[0]), args[1]); if (processInstanceList != null) { for (ProcessInstance instance : processInstanceList) {
System.out.println(" >> Instance: "
Listing 6.5 Example code for running the listProcessInstance method
f
g
h
Acquires jBPM Context
Call to fetch process instances
174 CHAPTER 6 jBPM tasks + instance.getId() + " Started:" + new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss z") .format(instance.getStart())); } } jbpmContext.close(); } }
In the example from listing 6.5 (included in the book’s source code), the Main class accepts two parameters: a processId and a search filter. Those values, in turn, are passed to the listProcessInstances method we created in listing 6.4. If any match- ing results are found, it simply prints some information about the process instance to the console. What has this exercise accomplished? We’ve demonstrated how, through the use of the API, we can return a filtered list of process instances associated with a given jBPM process. This could be useful apart from any task-related functions, such as for populating a desktop gadget or dashboard for executives.
Next, let’s build on this and use the API to return a list of all open tasks associated with a given process instance.
6.5.3 Finding open tasks within a process instance
Now that we’ve established what process instances are running, we are in a position to interrogate a given instance to determine what open tasks might exist. This API call is particularly relevant if you’re developing your own forms front-end to jBPM tasks. For example, you could create your task collection and approval forms in Flex (AIR), GWT, or another framework.
The operation for fetching a list of one or more tasks within a process instance is similar to the one we used in listing 6.4 to retrieve the process instances. We’ll again use Hibernate’s Query object to dynamically build an SQL statement String based on filter criteria provided as method parameters. Once a given task is returned, further
API operations can be performed to return the details of a task, such as assignment details, task variables, and associated timers. First, listing 6.6 will return a List of TaskInstances based on the parameters passed to the listTaskForProcessInstance.
public static List<TaskInstance>
listTasksForProcessInstance(JbpmContext jbpmContext , long processInstanceId, String filter) {
Query query; StringBuffer queryText =
new StringBuffer("select ti from"
+ " org.jbpm.taskmgmt.exe.TaskInstance as ti "); if (processInstanceId != 0)
queryText.append(" where ti.processInstance = " Listing 6.6 Retrieves list of tasks for a given process ID
Defines Hibernate Query
175 Developing with the task API
+ String.valueOf(processInstanceId)); if (filter.equalsIgnoreCase(ENDED)) {
queryText.append(" and ti.isOpen = false"); }
if (filter.equalsIgnoreCase(SUSPENDED)) {
queryText.append(" and ti.isSuspended = true"); }
if (filter.equalsIgnoreCase(CANCELLED)) {
queryText.append(" and ti.isCancelled = true"); }
if (filter.equalsIgnoreCase(OPEN)) {
queryText.append(" and ti.isOpen = true"); }
queryText.append(" order by ti.priority asc");
query = jbpmContext.getSession().createQuery(queryText.toString()); List<TaskInstance> taskInstanceList = (List<TaskInstance>) query.list(); return taskInstanceList;
} In the case of tasks, the four most common statuses are ENDED, SUSPENDED, CANCELLED, and OPEN (additional criteria could be added, such as filtering by actor or whether it’s past due). For a client class using this listTasksForProcessInstance method, the TaskInstance objects returned within the List provide a wealth of information about a given task. Listing 6.7 is a code fragment that shows details being printed about a given task, picking up at the point where you’ve received a TaskInstance (referred to as the variable taskInstance). System.out.println(">> Task: " + taskInstance.getId()
+ " Created: "
+ new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss z")
.format(taskInstance.getCreate())
+ " Task Name: " + taskInstance.getName());
System.out.println(" >> assigned actor is: " + taskInstance.getActorId()); Set pooledActors = taskInstance.getPooledActors();
PooledActor actor; Iterator it; for (it=pooledActors.iterator();it.hasNext();) {
actor = (PooledActor) it.next();
System.out.println(" >> pooled actor is: "
+ actor.getActorId()); }
In listing 6.7, we’re simply printing details about a given task, such as when it was created, its ID, name, and assigned actor. Then, using the TaskInstance.getPooledActors
Listing 6.7 Using a TaskInstance to retrieve information about a given task
Adds order by for sorting
Returns result List
Outputs details about task
Outputs actor assigned task Retrieves assigned pooled actors
Iterates actors, prints details
176 CHAPTER 6 jBPM tasks
Next, let’s look at how we can find all tasks that are assigned to a particular user, regardless of the process instance.
6.5.4 Finding all tasks assigned to a user
The ability to locate all open tasks for a user or actor would be a common require- ment of anyone building a custom front end to jBPM. As it turns out, this is easy to do because jBPM provides a TaskMgmtSession object, available through the JbpmContext. TaskMgmtSession provides a method, findTaskInstances, that allows you to find all tasks assigned to a given actorId (as you recall, actorId is just a string value that can be any arbitrary value). Thus, our listAssignedActorTasks helper method is terse:
public static List<TaskInstance>
listAssignedActorTasks (JbpmContext jbpmContext,String actorId) { List<TaskInstance> taskList =
jbpmContext.getTaskMgmtSession().findTaskInstances(actorId); return taskList;
}
The listAssignedActorTasks receives, as its sole parameter, an actorId. Then the TaskMgmtSession’s findTaskInstances method is used to return a List of Task- Instance objects. Once received, a client can process the TaskInstance in the same way as in the previous example (listing 6.7). Let’s consider next how to determine what pooled tasks are assigned a given actor.
6.5.5 Finding all pooled tasks for an actor
As you may recall from section 6.2, a pool of actors can be identified for a given task. Once the task is initiated, any of the pooled actors can assign themselves (or be assigned, in certain circumstances) the task. Obviously, this is useful in circumstances where multiple individuals can perform a certain task. You can also, by default, assign a task to a given actor, but any pooled actor can then reassign the task to themselves. The helper method we’ll create for this task is called listPooledActorTasks, and it’s nearly identical to the one described earlier for identifying assigned tasks. The one exception is that we’re using a different TaskMgmtSession method, findPooledTask- Instances, instead of findTaskInstances. Beyond that, this method is identical to listAssignedActorTasks, so I won’t show the code.
NOTE The TaskMgmtSession.findPooledTaskInstances method won’t return a task result if the task has already been assigned from the pool of users to a single actor. The purpose of this call is to identify unassigned tasks where an actor is a principal.
An unassigned task can be assigned to one of the pooled users by using the method TaskInstance.setActorId, which takes the String actorId as its parameter. Let’s conclude our Task API coverage by looking at how you can complete a task.
177