9 Replies Latest reply on Dec 9, 2005 1:30 PM by kukeltje

    Jbpm saveProcessInstance design

    ejimenez

      Hi All,

      It seems to me that there's somewhat of a design flaw in the way jbpm process instances are saved. In my mind, one of the advantages of jbpm seemed to be the ability to signal a token on a process, let actions do their work and propagate execution via signal until they find a state where they need to wait for an external system, and at the end of the work (when the big bad signal returns) we can do one big bad save that will persist the entire state of the process. So far so good for processes with no subprocesses.

      When subprocesses enter the picture, it gets complicated. Lets say we have process A that calls process B and process B calls process C. Because process instances only ever know if their token has a super-process, saving process instance A does not save process instance B or C, unless process C enters a wait state, in which case you would be able to query the token for process instance A for a subprocessInstance and B and so on until you find that the subprocessInstance is null (which means, no more children).

      That means that say, if process C had several decision nodes, and ends up going to the end state without ever hitting a state where execution propagation is required (an action in a node-type node for instance), process C could never be saved!!!!

      So far the only viable workaround is to add an action at an end state that forces the process to be signaled and saved, but in my mind is somewhat of an ugly workaround, that (at least under our structure) also forces us to save at every single token.signal() along a process execution, something we would really like to avoid for efficiency purposes.

      If I'm making a huge mistake please let me know :(

      Thanks,

      Ed

        • 1. Re: Jbpm saveProcessInstance design
          ejimenez

          Well, came up with another workaround, used the subprocess-created and subprocess-end events in the process-state node to save the process instance....

          • 2. Re: Jbpm saveProcessInstance design
            tom.baeyens

            you might have a very specific situation where subprocessing fails.

            in case you have multiple subprocesses that don't have wait states. because the token has only 1 pointer to the current subprocess.

            we might fix this later but this has no priority atm. although we also want to support processes without wait states, they are not our main target and it is considered a rare situation.

            regards, tom.

            • 3. Re: Jbpm saveProcessInstance design
              tom.baeyens

              the real solution will be to keep a list of all the subprocesses in the ProcessInstance (in a member that is not persisted with hibernate)

              then the save operation can take this list and store the subprocesses properly. this technique is similar as with e.g. logs, timers, ...

              regards, tom.

              • 4. Re: Jbpm saveProcessInstance design
                ejimenez

                Yes, agreed, that might be the best solution. But, here's another problem. The subprocess-end event is useless if the context's token does not have the subProcessInstance field set.

                See, token.subprocessinstance is not a persistent field, which means that if the subprocess is started, then loaded in a different hibernate session later, the token.subprocessinstance field is null, which means that if you have an action on a subprocess-end event, its not going to know which subprocess ended.

                making the list of subprocesses is great, but it doesn't solve this problem. My gut feeling is that this should be treated as it is treated during subprocess creation:

                 public void execute(ExecutionContext executionContext) {
                 Token superProcessToken = executionContext.getToken();
                
                 // create the subprocess
                 ProcessInstance subProcessInstance = new ProcessInstance(subProcessDefinition);
                 // bind the subprocess to the super-process-token
                 superProcessToken.setSubProcessInstance(subProcessInstance);
                 subProcessInstance.setSuperProcessToken(superProcessToken);
                
                 // fire the subprocess created event
                 fireEvent(Event.EVENTTYPE_SUBPROCESS_CREATED, executionContext);
                 .....
                


                See how the superProcessToken gets a nice setSubProcessInstance? That way the subprocess-created event knows which subprocess was created.

                The current code on notifySubProcessEnd is:

                public void notifySubProcessEnd(ProcessInstance subProcessInstance) {
                 Token superProcessToken = subProcessInstance.getSuperProcessToken();
                
                 ExecutionContext executionContext = new ExecutionContext(superProcessToken);
                
                 // feed the readable variables
                 if ((variableAccesses != null) && (!variableAccesses.isEmpty())) {
                 ....
                 ....
                 }
                
                 // feed the readable variables
                 fireEvent(Event.EVENTTYPE_SUBPROCESS_END, executionContext);
                 ....
                


                I think it is very reasonable to do instead

                public void notifySubProcessEnd(ProcessInstance subProcessInstance) {
                 Token superProcessToken = subProcessInstance.getSuperProcessToken();
                 superProcessToken.setSubProcessInstance(subProcessInstance);
                 ExecutionContext executionContext = new ExecutionContext(superProcessToken);
                
                 // feed the readable variables
                 if ((variableAccesses != null) && (!variableAccesses.isEmpty())) {
                 ....
                 ....
                 }
                
                 // fire the subprocess ended event
                 fireEvent(Event.EVENTTYPE_SUBPROCESS_END, executionContext);
                 ....
                


                In this way, the subprocess-end event will pass a context where the token correctly contains the subprocess instance even if being loaded after being persisted while the subprocess was going on.

                I will post a JIRA bug with this same info.

                • 5. Re: Jbpm saveProcessInstance design
                  ejimenez

                  tom, processes with no wait states are rare. Our process do have wait states wrapped in decision nodes. Because all the decisions are negative, the subprocess doesn't have anything to do so it ends.

                  One more thing, how could you have multiple subprocess per token?

                  If you want to start multiple processes you'd have to Split, which means you would have multiple tokens and each would have a different superprocessinstance, right?

                  • 6. Re: Jbpm saveProcessInstance design
                    ejimenez

                    Bug is in JIRA: JBPM-462

                    • 7. Re: Jbpm saveProcessInstance design
                      kukeltje

                      right, one subprocess per token

                      • 8. Re: Jbpm saveProcessInstance design
                        ejimenez

                        by split I meant fork :-p

                        • 9. Re: Jbpm saveProcessInstance design
                          kukeltje

                          isn't a fork a splitted spoon?