1 2 Previous Next 15 Replies Latest reply on Oct 13, 2005 6:10 PM by julian_k

    3.0.1, process flow continues after process.end()

    brittm

      I 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

        • 1. Re: 3.0.1, process flow continues after process.end()
          giancarlocadei

          I've a similar problem,
          When a process instance terminate I can get again the task the terminated task instance on the last user who terminate the process and also I've a new instance for the last node (the one that bring to the end of the process)

          Last part of the process definition:
          <task-node name="modify wi 2">



          <variable name="managementPage" mapped-name="wiMod3.jsp"/>




          </task-node>

          <end-state name="end" />

          How I close the process instance:
          ProcessInstance processInstance = taskInstance.getTaskMgmtInstance().getProcessInstance();

          if ("ok".equals(transitionButton)) {
          taskInstance.end();
          if(taskInstance.getName().equalsIgnoreCase("modify wi 2")){
          processInstance.end();
          }
          } else

          How I get the task list:

          taskMgmtSession.findTaskInstances(userBean.getUserName());

          Thanks in advance.


          • 2. Re: 3.0.1, process flow continues after process.end()
            brittm

            If you're ending the process, you will want to manually end any outstanding tasks in your code (see my example code). If you do that in your particular case you shouldn't see any tasks listed for that process when you call taskMgmtSession.findTaskInstances(userBean.getUserName());

            The problem occurrs when the process advances to the next node despite having been ended--and you actually have stuff in that node, like more tasks that get created.

            No one seems to be talking about this (or I just haven't found the threads). I'm glad someone else has observed the problem. Now if someone can help us determine if this is actually an API problem that needs to be fixed, or if we're just brain dead in how we're using it.

            I'd have spent more time looking under the hood myself on this, but I've been busy spending my extra time chasing down Swimlane pooledActor issues.

            -Britt

            • 3. Re: 3.0.1, process flow continues after process.end()
              aguizar

              Britt, there is something that is not obvious to me here: how come the ended token advances, given that your code doesn't give it a signal() anywhere?

              Anyway, a token doesn't check whether it has been ended before leaving a node. Probably jBPM should check for this situation and either ignore the signal silently or throw an exception.

              • 4. Re: 3.0.1, process flow continues after process.end()
                brittm

                Alex,

                Thanks for pointing that out about the signal(). The <task-node> "signal" attribute default is signal="last". This ensures that completing (ending) the last task in the node automatically advances on the default transition--cancelling a task also ends it. In this case especially, the internal signal should be ignored if a process has been cancelled.

                Unfortunately there is no "cancelled" flag on a process or token to check to determine if the default signal should be ignored--we rely on process instance variables of our own definition for identifying cancellations.

                Setting <task-node signal="never"> solves the problem and prevents advancement when the process is cancelled; however, to use this effectively, basically any process that could ever be cancelled would always need all its tasks nodes set to signal="never". That kind of defeats the purpose of having the attribute.

                Your comment about ignoring the signal, in combination with a "cancelled" flag on the process, would make the issue solvable.

                Thanks,
                Britt

                • 5. Re: 3.0.1, process flow continues after process.end()
                  brittm

                  err...maybe ignore what I said about the "cancelled" flag; checking for an ended token would be sufficient.

                  -Britt

                  • 6. Re: 3.0.1, process flow continues after process.end()
                    aguizar

                    Would checking for a null/not null end date and ignoring the signal accordingly do the job? I don't think the reason why the token was ended should influence the reaction to a signal.

                    • 7. Re: 3.0.1, process flow continues after process.end()
                      brittm

                      Yes. That's what I was trying to say with my "err..." comment.

                      • 8. Re: 3.0.1, process flow continues after process.end()
                        tom.baeyens

                        if a process instance or a token is cancelled, jbpm should modify all the related task instances and set signalling of those tasks to false: http://jira.jboss.com/jira/browse/JBPM-392

                        on the checking for completion: checking (e.g. for token completion or when a token is waiting in a fork) is still something on which i am in doubt. normally, the software surrounding jbpm works in such a way that doesn't require checking from jbpm.

                        building in these checks could lead to problems when people want to do something tricky or performance problems.

                        so i'm not yet sure if this is a good idea to do it in a general case.

                        regards, tom.

                        • 9. Re: 3.0.1, process flow continues after process.end()
                          alal007

                          I am also facing exactly sam eissue
                          any workaround for this?

                          • 10. Re: 3.0.1, process flow continues after process.end()
                            aguizar

                            Instead of having the token check if it is ended, we can have the task node perform this check for the values of the signal attribute that ask for automatic advance. Does this make sense?

                            • 11. Re: 3.0.1, process flow continues after process.end()
                              alal007


                              any code examples will be helpful

                              • 12. Re: 3.0.1, process flow continues after process.end()
                                julian_k

                                I would like to further this topic by adding that simply signalling the end of the current taskintance(s) (per brittm's code) may not be enough. As stated before when the process is ended, the next state is signalled. However, if it is a task-node, the task will be created without an end date...wich makes it come up when calling taskMgmtSession().findTaskInstances(actorId); I currently have a view which filters this out, but it still could be a performance bottleneck.

                                Regards,
                                Julian

                                • 13. Re: 3.0.1, process flow continues after process.end()
                                  russelldb

                                  I do work around this by doing exactly what Brittm does except I add the line

                                   ti.setSignalling(false);
                                  

                                  before
                                  if(!ti.hasEnded()) ti.cancel();
                                  


                                  I know it is obvious so sorry if I am teaching you to suck eggs.

                                  • 14. Re: 3.0.1, process flow continues after process.end()
                                    brittm

                                    That is right russelldb, until http://jira.jboss.com/jira/browse/JBPM-392 is resolved, this would be a good, working code example for handling a cancellation:

                                    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", reason);
                                     pi.getContextInstance().createVariable("cancelled_by", userId);
                                    
                                     //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 this process instance
                                     // and cancel them if they are still active.
                                     String hql = "from "+TaskInstance.class.getName()+" as ti where ti.token.processInstance = :instance and ti.end IS NULL" ;
                                     Query hqlQuery = jbpmSession.getSession().createQuery( hql );
                                     hqlQuery.setEntity("instance", pi);
                                     List tasks = hqlQuery.list();
                                     if(tasks != null && tasks.size() > 0) {
                                     for (Iterator itr = tasks.iterator(); itr.hasNext();) {
                                     TaskInstance ti = (TaskInstance)itr.next();
                                     //if the process def doesn't set signal="never", we have to manually turn off
                                     // signaling for all tasks; otherwise, the token will advance despite being ended.
                                     // Do this until http://jira.jboss.com/jira/browse/JBPM-392 is resolved
                                     ti.setSignalling(false);
                                     ti.cancel();
                                     }
                                     }
                                    
                                     graphSession.saveProcessInstance(pi);
                                     jbpmSession.commitTransaction();

                                    -Britt

                                    1 2 Previous Next