10 Replies Latest reply on Apr 12, 2006 5:47 AM by hoogenbj

    How to let process stay in node "for ever"?

      Hi Everyone
      I want to have a node which executes a process for every item in a list. What complicates things is that only one item must be processed per signal.
      I thought I could do it with a custom actionhandler on a node and just not call context.leaveNode() until all the items are done.
      On the first signal the execute() method my actionhandler gets executed and the first item gets processed. However, when the root token is signalled again, execution moves on to the next node via the default transition instead of staying in my node and calling my execute() method again.
      Is this by design or is this (yay!) a bug?
      The docs say the node behaves like a wait state if leaveNode is not called. Please tell me this means "wait forever until leaveNode() is called".
      Because this will simplify things a lot!
      Regards
      Johan

        • 1. Re: How to let process stay in node

          Hi,
          I posted this some time ago:

          "Hi Everyone
          I want to have a node which executes a process for every item in a list. What complicates things is that only one item must be processed per signal.
          I thought I could do it with a custom actionhandler on a node and just not call context.leaveNode() until all the items are done.
          On the first signal the execute() method my actionhandler gets executed and the first item gets processed. However, when the root token is signalled again, execution moves on to the next node via the default transition instead of staying in my node and calling my execute() method again.
          Is this by design or is this (yay!) a bug?
          The docs say the node behaves like a wait state if leaveNode is not called. Please tell me this means "wait forever until leaveNode() is called".
          Because this will simplify things a lot!
          Regards
          Johan"

          Can someone please answer?

          • 2. Re: How to let process stay in node
            koen.aers

            Johan,

            This is by design. If you want to return to the node and execute it again, the node should have a transition back to itself and you should call signal("transitionName").

            Regards,
            Koen

            • 3. Re: How to let process stay in node
              koen.aers

              And the behaviour is not exactly 'wait forever until leaveNode() is called' but 'wait forever until signal() is called', which is indeed almost the same thing...

              Regards,
              Koen

              • 4. Re: How to let process stay in node

                Thank you Koen.
                A transition from the node to itself is ok if you want to keep executing the node until some condition changes, but not if you want to wait in the node until some condition changes.
                See, I want the node to get the signal and pass it through to the sub-process, but itself must wait until the sub-process is executed for each item in the list - and the sub-process must be allowed to have any kind of node. This way the program (?) exercising the main process does not have to be aware of the fact that a sub-process is being executed.

                I eventually modeled it like this:

                <?xml version="1.0" encoding="UTF-8"?>
                
                <process-definition
                 xmlns="" name="auth.user.edit">
                 <start-state name="start">
                 <transition to="PageFlow: Selection screen">
                 <action name="RetrieveUsers" class="com.izazi.service.converse.web.RetrieveUsersActionHandler"></action>
                 </transition>
                 </start-state>
                 <state name="PageFlow: Selection screen">
                 <event type="node-enter">
                 <action name="PageFlow" class="com.izazi.service.converse.web.PageFlowActionHandler">
                 <pageName>auth_user_select</pageName>
                 </action>
                 </event>
                 <transition to="end1"></transition>
                 <transition name="groups" to="Edit groups"></transition>
                 </state>
                 <end-state name="end1"></end-state>
                 <node name="Edit groups">
                 <action name="ForEach" class="com.izazi.service.converse.web.ForEachActionHandler">
                 <itemExpression>items</itemExpression>
                 <subProcess>auth.edit.group</subProcess>
                 </action>
                 <transition to="PageFlow: Selection screen"></transition>
                 <transition name="loop" to="Loop Edit Groups"></transition>
                 </node>
                 <state name="Loop Edit Groups">
                 <transition name="" to="Edit groups"></transition>
                 </state>
                </process-definition>


                This is more messy than I would've like liked, because now the process diagram contains extra detail that really should be hidden away in actionhandlers. It is a principle put forward in your docs. To quote:
                It is not acceptable if the developer must change the graphical diagram to include a technical detail in which the business analyst is not interested.

                At least now I know it is by design (*sigh*).
                Thanks
                Johan

                • 5. Re: How to let process stay in node
                  koen.aers

                  If you want a node with 'for-each' semantics upon a collection, you can always write an action-handler that does this. In principle, there is no need to disturb the processdefinition graph for this.

                  Regards,
                  Koen

                  • 6. Re: How to let process stay in node

                    Koen, if that was all I wanted to do, then, yes, an actionhandler will give me that. But that's not all I want. My process definition drives a page flow. By definition such a process definition includes wait states - one for every input page at least. At some point I want another (sub) process definition (page flow) to be executed for every item in a list. The sub process is a sub page flow with wait states. Again every wait state equals an input page. What I would've liked is for a signal to the node in the main process to cause the sub process token to move along to the next node, but the token in the main process definition stays put.

                    • 7. Re: How to let process stay in node
                      koen.aers

                      Hm, there is some inconsistency here. What if the subprocess spawns again a subprocess and then another subprocess... What would a signal to the mainprocess then be supposed to do? What if you want to cancel one of these running subprocesses?
                      There is no reason you should not signal the token of these subprocess instances IMO. And as for the 'for-each' semantics. You can write a node which is basically a process-state with for-each semantics if you would like to do that... and then at each time spawn a subprocess.

                      Regards,
                      Koen

                      • 8. Re: How to let process stay in node

                        You can let me worry about the "inconsistency":-)
                        The main thing for me is that the "program" sending the signals should not care whether it is sending the signal to the main process or the sub-process.

                        That, incidentally, happens to be the problem I have with using process-state. In your "testWithSubProcess" method in org.jbpm.graph.exe.SubProcessPlusConcurrencyDbTest, the "program" sending the signals needs to be aware that there is a sub process so that it can retrieve the sub process instance and send signals to it.

                        Are you saying I should write my own custom version of a process-state?
                        I wouldn't mind, but I would want such a thing to be available to GPD, and I would still like to not have to care about having to send the signals directly to the sub-process. If that is possible (it didn't seem likely after my first glance at the code), I'm up for it.

                        • 9. Re: How to let process stay in node
                          koen.aers

                           

                          "johan" wrote:
                          You can let me worry about the "inconsistency":-)
                          The main thing for me is that the "program" sending the signals should not care whether it is sending the signal to the main process or the sub-process.

                          You *have* to communicate the id of the processinstance or the id of the token you want to signal to jBPM. This id must be available to the client program doing this signal in the first place. I don't see any difference in providing the id of the 'master' process as opposed to providing the id of a 'sub' process. For the client program this should be totally transparent.

                          "johan" wrote:
                          Are you saying I should write my own custom version of a process-state?

                          Exactly. The whole idea behind jPDL and jBPM is that we cannot provide all the constructs to satisfy all the process analists in the world. You can always plug the node in the GPD afterwards. There are extension points for doing this.

                          Regards,
                          Koen

                          • 10. Re: How to let process stay in node

                            "Koen" wrote:

                            For the client program this should be totally transparent.

                            Koen, I'm sure you'll agree with me that the sub process in the following code is not transparent to the client program at all:
                            ProcessInstance pi = jbpmContext.newProcessInstanceForUpdate("super");
                             pi.signal("with subprocess");
                            
                             ProcessInstance subPi = pi.getRootToken().getSubProcessInstance();
                             assertEquals("wait", subPi.getRootToken().getNode().getName());
                            
                             newTransaction();
                            
                             subPi = jbpmContext.loadProcessInstanceForUpdate(subPi.getId());
                             subPi.signal();

                            "Koen" wrote:
                            You *have* to communicate the id of the processinstance or the id of the token you want to signal to jBPM.

                            There's no disputing that. However I see no reason why I shouldn't be able to keep signalling the main process and rely on some custom-or-maybe-not-custom-newfangled-waiting-process-state-node to pass on the signal to the sub-process(es) until those are done and then allow the token to move on to the next process node in the main process. Voila! There's your transparency. But hey, we don't have to argue anymore about this. I still love jBPM.

                            On the writing a custom node bit: you make it sound so easy :-) Any chance of an example somewhere?