7 Replies Latest reply on Sep 13, 2008 1:10 PM by kukeltje

    signaling to a forked sibling

    gnagy

      Hello,

      We have a workflow where a number of observers need to observe a number of items. A possible dependency relationship is such:


      Process
      / \
      Observer1 Observer2
      / \ / \
      Item1 Item2 Item3


      An observer can only continue in the workflow if all observed items were "activated". So e.g. Observer1 can only continue after it gets a signal from both Item1 and Item2.

      A possible chain of events after fork:

      I1 activates, O1 notices, but does not continie (I2 not activated)
      I2 activates, O1 notices, continues, O2 notices, but stays put
      I3 activates, O2 notices, continues (I2 was activated)

      We are trying to solve this as follows. O1,2 are state nodes, I1,2,3 are task nodes. The workflow branches to O + I branches:


      |
      .------ FORK ------.
      | | | | |
      O1 O2 I1 I2 I3
      | | | | |


      When any Item activates, it sends an event that Os can see, and the Os decide if they can continue.

      I just don't really know how to implement this with jbpm, or if this is a good way the solve the problem.

      Any help appreciated.


      Thanks,
      Greg

        • 1. Re: signaling to a forked sibling
          kukeltje

          yikes... hmm... I would solve it a completely different way I think. More datadriven.

          Why not make I1,I2 and I3 variables. Have two states. O1 and O2, each with a decision under them. Each decision has two outcomes, one back to the state and one to a next state. Each time one of the variables get's updated, you signal both states which then go to the decision and each decision checks the values of the variables and decides which transition to take. These decisions can be in java, drools, script or....

          One other solution is to just have two states with one outcome (go-further) and put the decisions AND signalling of states in drools. You can decide there which of the states to signal.

          Hope I gave you some more info..... either way.... if you could (as you promised to do from now on ;-) ) make this in a unit test, please post it. We need more of these examples.

          • 2. Re: signaling to a forked sibling
            gnagy

            Well, the reason we modeled the process like this, and I guess I wasn't clear about that in the original post, is that the observer and item "states" are a actually processes with multiple steps that need to be synchronized.

            The item side represents sub-processes about postal mailing to certain parties, with states (mostly tasks to be performed by a human) like generating mail, mail sent, mail not received (loop back if threshold not exceeded, fail otherwise), mail received (notify observer side), etc, and the observer side can only continue from certain states when *all* involved parties have been notified.

            I'm not sure how much I can tell you about our actual business process, but if it is useful to the community I can cook up some example test case to showcase how we implemented the fork, as the fork is really a generic node with an action handler to control the token propagation, setting branch-local variables (such as info about the mailed party) on the child tokens, etc...

            So in light of all this would you still recommend against such approach? I'll have a look at making the observer wait states decision nodes, but I guess since the decision is basically stay there or continue, it is better to use State nodes somehow...

            BTW we had a look at drools (for authentication), but since our domain objects are rather complex drools turned out to be rather cumbersome (it's really good at deciding on direct properties of an object (like foo.bar), but when we needed to make decisions on foo.bar[].baz.xul, it started to look a lot like java code, so we finally implemented the rules in java, but closely modeled after drools, i.e. through Identity.hasPermission(name, action, data).

            Thanks,
            Greg

            • 3. Re: signaling to a forked sibling
              kukeltje

              I've been thinking a little more about this and it indeed contains generic requirements. I have one question though. In your original post you say

              So e.g. Observer1 can only continue after it gets a signal from both Item1 and Item2.


              What is 'continue' here? Is the subprocess in a certain state and can continue from there? Is the subprocess not even started? When you give me these details, I think we can work out a nice solution. Using events is indeed an option where you combine my state/decision 'block' into an eventhandler on a state (that is what I got from re-reading your initial post)



              • 4. Re: signaling to a forked sibling
                gnagy

                > Is the subprocess in a certain state and can continue from there? Is the subprocess not even started?

                Yes, the observer sub-process(es) are in a waiting state, doing nothing but waiting for all affected items to get past a certain state (mail delivered).

                Initially i guess you could say that the observer sub-process has not started yet, because the wait state is the first state in that branch, so it is a technicality whether we first branch and then wait, or if we wait before the branch. However later in the process another mail notification is needed when another state completes on the observer side, with the same requirement to wait for all affected parties to be notified, so I decided to fork and wait for the first mailing as well to keep things similar.

                A possible sequence of events: 1 observer, 2 parties
                Branch
                -Observer: wait for all parties to be notified
                -Party1: send mail to party1
                -Party2 send mail to party2
                -Party1: mail could not be delivered, resend mail
                -Party2: mail was delivered
                -Party1: mail was delivered
                -Observer comes out of wait state, goes to anotherimportantbusinessstep state
                -Observer completes anotherimportantbusinessstep, goes to wait state because parties need notification
                -Party1: send mail2 to party1
                -Party2 send mail2 to party2
                -Party2: mail2 was delivered
                -Party1: mail2 was delivered
                - Observer finishes wait state, goes into another business state
                - somewhere near the end of the process branches join
                - whole process completes

                The reason to include such steps for the mailing is because our customer wants to track the physical mailing process (print document, take it to the post office, etc), so they are task notes in a "todo list". Same with most of the observer states, that are real world tasks that are tracked by the system.

                • 5. Re: signaling to a forked sibling
                  kukeltje

                  ok, clear... and it becomes 'difficult' when you have 2 observers and e.g. 3 parties where observer 1 has to wait for party 1 and 2 and observer 2 for party 2 and party 3 as stated in your first post.

                  Let me think about this for day and I'll get back to you

                  • 6. Re: signaling to a forked sibling
                    gnagy

                    I think I managed to fire a user-defined event, but i cannot see the effect on the observer branch (the "Firing mail-delivered" message does appear on the console). Does this make sense at all? Can such an event be seen in another branch?

                    (party branch)
                    [task-node name="waitingforL1"]
                    [task name="Waiting for L1" swimlane="ahstaff"][/task]
                    [transition to="waitingforsendingL2" name="gotL1"]
                    [script]System.out.println("Firing mail-delivered "); executionContext.getTransition().fireEvent("mail-delivered", executionContext);[/script]
                    [/transition]
                    [/task-node]

                    (observer branch)
                    [state name="waitingforallL1"]
                    [event type="mail-delivered"]
                    [action][script]System.out.println("mail-delivered event handled"); node.leave(executionContext);[/script][/action]
                    [/event]
                    [transition to="nextstep" name="gotallL1"][/transition]
                    [/state]

                    Thanks,
                    Greg

                    • 7. Re: signaling to a forked sibling
                      kukeltje

                      rthis was kind of what I had in mind as well. The problem is going to be how to check/remember if both events have occured. And what if you have more than 2... use process-variables or check the state of a node/task? The latter would be better I think.

                      btw... you can post in xml if you surround that part by [c o d e] [/c o d e] tags (without spaces) you can also include a minimal unit test then.

                      I'll see what this approach does for me.

                      The other soultion is to use a guarded transitions which e.g. check the processvariables mentioned above and write some code that signals the other nodes. Whether it continues depends on the variables then.

                      btw, I send you a message on greg(a)gnome_hu. Is that correct?