1 Reply Latest reply on Apr 6, 2007 4:34 AM by Koen Aers

    Fork Node Issues

    Kannan Ekanath Newbie

      I have a workflow where I need a fork and one of the paths is readonly. For example, when a student submits a request to a teacher for a leave, he needs to get the task in "Leaves awaiting approval" list, (He cant change anything though). For this we wrote a custom join node, which does the joining, and also terminates all readonly tasks in the parent token (Apologies, for posting a slightly big xml file, but I couldnt make it any simpler to demonstrate my point)

      <task-node name="Student Submits Leave">
       <task name="Create Leave Request" swimlane="student"/>
       <transition name="fork1" to="Fork Leave Request"/>
      <fork name="Fork Leave Request">
       <transition name="Read Only" to="Leaves sent to teacher"/>
       <transition name="Read Write" to="Pending Approval"/>
      <task-node name="Leaves sent to teacher">
       <task name="Leave requests sent to teacher" swimlane="student"/>
       <!-- The UI will just show a readonly jsp page-->
       <transition name="" to="JoinStudent"/>
      <task-node name="Pending Approval">
       <task name="Pending Approval" swimlane="teacher"/>
       <!-- Teacher can approve/send to principal-->
       <transition name="" to="JoinStudent"/>
      <custom-join name="JoinStudent"> <!-- This will terminate the read only token -->
       <transition name="" to="Principals Review"/>
      <task-node name="Principals Review">
       <task name="Principals Review" swimlane="principal"/>
       <!-- Teacher can approve/send to principal-->
       <transition name="" to="Pending Approval"/>

      So a principal reviews the request from the teacher, and if he finds it ok, sends again to the principal, so that he can do a final approval (those parts are not shown here)
      a) The node ("Pending Approval") has to be exactly the same, whether the request is coming from student for first time, or if it is coming from the principal
      b) Now when the first time join is invoked, i am setting token.setAbleToReactivateParent as false meaning the token cannot do a join anymore :), so when the same token is coming back from principal, the workflow stops there.

      To avoid this, we added an else clause
       public void execute(ExecutionContext executionContext) {
       Token token = executionContext.getToken();
       if (token.isAbleToReactivateParent()) {
       Token parentToken = token.getParent();
       if (parentToken != null) {
       //go ahead and terminate all sibling tasks
       } else {
       logger.debug("Token[" + token + "] is itself a parent");
       //This is the case of the token coming from principal

      I would like to know, if there is someone who has encountered a similar issue, If yes, is there a recommendation for this. I went through the code, in Join class of JBPM and there is no else part there. The essence is that you dont expect a Join call when there is no fork, for me there is a node, which could have come as a result of a fork and in some cases it might not be from a fork (in this case from principals review node)

        • 1. Re: Fork Node Issues
          Koen Aers Master

          There are different solutions to this problem, but I would not create a custom join node for it.

          1. You could use two tasks on a single task-node, the read-only task assigned to the student is not 'endable' and it can only end when the second task is ended. To do this, end the read-only task from an action handler that is triggered on the task-end event of the second task.

          2. You could use two task-nodes and play with the signalling attribute of the read-only task. Set the signalling attribute to never and recreate a task for this task node eacht time the read-only task is ended (in an action handler triggered in the task-end event). For the other task, again in an action handler triggered in the task-end event, cancel the pending read-only task and signal its token. It is possible that you have to use an asynchronous mechanism for this option because of synchronization issues in the join.

          I would personally opt for the first choice.