3 Replies Latest reply on Apr 12, 2006 5:41 PM by kukeltje

    conditional Fork: execute NOT all transition

    hannes

      (jbpm:3.0.2)
      Hi there,
      I have following use case:

      +----+
       |Fork|
       +----+
       / \
       +--------+ +-------+
       |State A | |State B|
       +--------+ +-------+
       \ /
       +-----+
       |Join |
       +-----+

      Now I want to execute all 4 possible cases:
      A B
      0 0: execute none of the (task)nodes, proceed with join
      0 1: execute only State B
      1 0: execute only State A
      1 1: execute both States

      There are controller variables in the context that decide whether the state should be executed or not.

      So I tried a simple conditioned transition:
      <fork name="fork1>
       <transition name="toStateA" to="State A">
       <script>
       <expression>isStateA.booleanValue()</expression>
       </script>
       </transition>
       <transition name="toStateB" to="State B">
       <script>
       <expression>isStateB.booleanValue()</expression>
       </script>
       </transition>
       </fork>

      But the beanshell scripts dont get considered and it forks into both transitions.
      When you throw a look on the Fork class:
      public void execute(ExecutionContext executionContext) {
       Token token = executionContext.getToken();
       Node forkNode = token.getNode();
      
       // phase one: collect all the transitionNames
       Collection transitionNames = null;
       List forkedTokens = new ArrayList();
      
       // by default, the fork spawns a token for each leaving transition
       if (script==null) {
       transitionNames = forkNode.getLeavingTransitionsMap().keySet();
      
       } else { // a script is specified
       // if a script is specified, use that script to calculate the set
       // of leaving transitions to be used for forking tokens.
       Map outputMap = script.eval(token);
       if (outputMap.size()==1) {
       Object result = outputMap.values().iterator().next();
       if (result instanceof Collection) {
       transitionNames = (Collection) result;
       }
       }
       if (transitionNames==null) {
       throw new RuntimeException("script for fork '"+name+"' should produce one collection (in one writable variable): "+transitionNames);
       }
       }
      ...

      You see, that there has to be directly a script under the fork-node, and that script has to have a list of the transition names as output.

      Ok, I could bybas this trouble by using several decision nodes (in this case 1 with 4 leaving Transition: ->A, ->B, ->fork, ->the node after the join), but if have more than 2 childs, it would quickly get very complicated.

      So, what do you recommend? Maybe its still possible with the the current (3.0.2) API/JPDL, maybe I missed some point.

        • 1. Re: conditional Fork: execute NOT all transition
          kukeltje

          Why not do somathing like

           +---------+
           | Fork |
           +---------+
           / \
           Decsision 1 Descision 2
           / | | \
           +--------+ | | +-------+
           |State A | | | |State B|
           +--------+ | | +-------+
           \ | | /
           +----------+
           | Join |
           +----------+
          

          Should work as well

          • 2. Re: conditional Fork: execute NOT all transition
            hannes

            hmm, yes, that way sounds reasonable.

            Anyway, I'll take a shot and try my own fork node - the processdefiniton.xml is already fat and so I can save some nodes. I have already started: the read-method similar to the decision-node, and in the execute-method only the right transitions get picked. Only thinking of the case if none of the transitions get executed... whereto sending the token?

            • 3. Re: conditional Fork: execute NOT all transition
              kukeltje

              cancelling the token would be an option. But if it is the root token, then the process gets cancelled. In my example it would not be and just go to the join. If that is what you want (it sould according to your previous statement)