4 Replies Latest reply on Nov 15, 2006 10:34 AM by mondenkind

    How to stop a process instance and all its task instances?

    sscortan

      Hello,

      How to finally stop a process instance in the middle of the workflow, if I have multiple nodes treated in parallel (inside fork-join nodes) and one actor decide to cancel the process?

      I have a process in jBPM 3.0 where from the start state I open a fork to 4 task nodes, treated in parallel.
      If one of the owners of these nodes in parallel wants to reject the process, I would like to stop the task instance, then to stop all other task instances which are not already finished and finally to end the process instance. The goal is to not allow the other owners of the nodes in parallel to see (and no more validate) their actions.

      I did like this:
      - get all unfinished tasks for the process instance and call taskInstance.setEnd(new Date()) for every task
      - get the token associated to every task from that list and call token.end()
      - call processInstance.end()

      I avoided to use taskInstance.end() because the end of the task instance does not mean the end of its token.

      This does work if only the actor which rejects the process is in front of a validation form. If two or many actors of the nodes in parallel are in front of their validation forms, their task instances are not set with an end date, even though the tokens and the process instance are ended.

      How to handle this?

      Thanks for any answer.

      Sorin

        • 1. Re: How to stop a process instance and all its task instance
          icyjamie

          Their is also a "cancel" on the taskInstance. All queries fetching taskInstances take into account "isCancelled=false". I don't know if this could be of any use also.
          You're kind of breaking the business rule if you do a setEnd, because the task is not ended, it is halted or cancelled.
          As for web application stuff: this is the same problem as any (web) application stuff: what you see can already be dirty, backend-wise. Best is to check the state in one transaction, locking it and committing it. You should decide whether race conditions are acceptable or not.
          Have a look at tests Wfp20CancelActivityTest and Wfp21CancelCaseTest to see how cancellation is handled. I think process.end() recursively calls the ending of the child.

          Maybe there will be native support for "cancel" or "suspend" in next release(s).

          • 2. Re: How to stop a process instance and all its task instance
            sscortan

            Hello,

            Thanks for you reply.

            I didn't use taskInstance.cancel() method for the unfinished tasks because it is calling end() method too, which marks those tasks as done, and that is not true, also. Those tasks should be cancelled and made "invisible" for the other actors.

            I avoided to use taskInstance.end(), which continues the token's execution.

            Because after this cancellation of the process all the tasks, tokens and the process instance must be ended, I preferred to set an end date for the task instance (token.end() and processInstance.end() made that for the other elements)

            Wfp21CancelCaseTest test class gives good ideas, but only at process instance's and token's level, not at task instance's level.

            The following code worked well for me:

            Collection listTasks = processInstance.getTaskMgmtInstance().getTaskInstances();
            if (listTasks.size()>0) {
             for (Iterator iter = listTasks.iterator(); iter.hasNext(); ) {
             TaskInstance ti = (TaskInstance) iter.next();
             if (!ti.hasEnded()) {
             ti.setEnd(new java.util.Date());
             log.debug("task instance " + ti.getName() + " has ended");
             Token tk = ti.getToken();
             tk.end();
             log.debug("token " + tk.getName() + " has ended");
             }
             }
            }
            if (!processInstance.hasEnded()) {
             processInstance.end();
             log.debug("process instance " + processInstance.getId() + " has ended");
            }
            


            But any better idea is welcome, too.

            Sorin

            • 3. Re: How to stop a process instance and all its task instance
              brittm

              Yes, calling process.end() does also end it's Tokens, BUT...this doesn't automatically cancel open tasks (maybe it shouldn't anyway--once a task has started, you may want it completed--just depends) so that Tasks continue to show up in Actor's queues; you will have to cancel the Tasks explicitly.

              This could possibly be managed by an attribute added to the task in the process definition: cancel=implicit | explicit. This would tell JBPM that a particular task should be implicitly cancelled when it's parent is ended, or require explicit cancellation by the user or system (for tasks that should typically be expected to finish once they've been started).

              -Britt

              • 4. Re: How to stop a process instance and all its task instance
                mondenkind

                sscortan's answer helped me a lot and verified what i already guessed. ending a processinstance and its taskinstances like that works fine. although i have a problem:

                if i manually set an end date with setEnd(Date), the state of the taskinstance is left untouched, which means it is still declared as open/signalling. so it never vanishes from my "open tasks" list, which is bad!

                what can i do to set it to ended without using the end() function or having proper functions to set the boolian of isOpen/isSignalling to false?!

                i can only think of manipulating the database directly with sql/hql, but that would be really dirty!

                thanks for your help!!