3.0.1, process flow continues after process.end()
brittm Sep 22, 2005 5:04 PMI thought I had brought this up a while back, and Ronald or someone had tied it to the never-ending timer, but I read that the timer has been fixed, and this is still a problem--If there is something else in the forums or Jira, I've missed it...
After calling processInstance.end(), process flow continues to advance (at least mine does :). Assume the following simple process definition:
<?xml version="1.0" encoding="UTF-8"?> <process-definition name="TestSimple"> <swimlane name="testLane"> <assignment class="com.ntc.workflow.GenericAssignmentHandler"> <actorId>brittm</actorId> <groupId>IT Developers</groupId> </assignment> </swimlane> <start-state name="START" > <task /> <transition to="NODE1"/> </start-state> <task-node name="NODE1"> <task name="node1_task" swimlane="testLane"/> <transition to="END"/> </task-node> <end-state name="END" /> </process-definition>
While in the start state, the process is cancelled with the following:
jbpmSession.beginTransaction(); //Record a standardized variable that we can use to determine that this process has // been 'cancelled' and not just ended. pi.getContextInstance().createVariable("cancelled", request.getParameter("reason") == null ? "" : request.getParameter("reason")); pi.getContextInstance().createVariable("cancelled_by", request.getParameter("actor") != null ? request.getParameter("actor") : user); //End the process instance and any open tokens pi.end(); //We may still have open tasks even though their parent tokens // have been ended. So we'll simply get all tasks from all tokens and cancel // them if they are still active. String hql = "from "+Token.class.getName()+" as t where t.processInstance = :instance" ; Query hqlQuery = jbpmSession.getSession().createQuery( hql ); hqlQuery.setEntity("instance", pi); List tokensForInstance = hqlQuery.list(); if(tokensForInstance != null && tokensForInstance.size() > 0) { for (Iterator itr = tokensForInstance.iterator(); itr.hasNext();) { Token t = (Token)itr.next(); List tasks = taskMgmtSession.findTaskInstancesByToken(t.getId()); Iterator taskItr = tasks.iterator(); while(taskItr.hasNext()) { TaskInstance ti = (TaskInstance)taskItr.next(); if(!ti.hasEnded()) ti.cancel(); } } } graphSession.saveProcessInstance(pi); jbpmSession.commitTransaction();
So the process has ended; however, the ended token will advance on to reference the NODE1 state, and the node1_task is created. Calling taskMgmtSession.findTaskInstances("brittm") will return the newly created node1_task as an available task for this actor. The actor can subsequently complete that task, and the ended process just keeps on rolling along. (This behavior is not unique to ending a process while in the start state--this is just a simple example.)
It may not matter in the least, but I may be starting my processes a little differently than some. Just for reference:
ProcessDefinition pd = graphSession.findLatestProcessDefinition(procDefName); jbpmSession.beginTransaction(); ProcessInstance pi = new ProcessInstance(pd); //This ensures that all swimlanes are initialized and available for reporting and reassignment immediately. //If we don't initialize them up front, they won't be created until a task calls for them. Map swimlanes = pd.getTaskMgmtDefinition().getSwimlanes(); Iterator itr = swimlanes.keySet().iterator(); while(itr.hasNext()) { Swimlane swimlane = (Swimlane)swimlanes.get(itr.next()); pi.getTaskMgmtInstance().getInitializedSwimlaneInstance(new ExecutionContext(pi.getRootToken()), swimlane); } //If this process definition defines a startTask in the StartState, we'll have to // explicitly create it--it won't be created otherwise... if (pd.getTaskMgmtDefinition().getStartTask() != null) { //Create the task in the new process (doesn't seem to happen otherwise). //The start task will be assigned to the currently authenticated user (as understood by Jbpm), and that // user WILL overwrite any default swimlane assignment. TaskInstance startTask = pi.getTaskMgmtInstance().createStartTaskInstance(); //Unless our application's authentication scheme has been tied into Jbpm's, we // should manually assign the startTask to a user as well as manually set the swimlane // referenced by this task, otherwise both will be null. startTask.setActorId(user); if(startTask.getSwimlaneInstance() != null) { startTask.getSwimlaneInstance().setActorId(user); } }else { //If our new process doesn't have a startTask defined, we may want to get the new process rolling... // Although, some executions may want to set process variables, etc. before // continuing, in which case they should do such and signal for themselves. //pi.signal(); } graphSession.saveProcessInstance(pi); jbpmSession.commitTransaction();
Thanks,
Britt