I am attempting to handle what to me is a difficult workflow problem. I believe a good metaphore for this process is: "Who's got the button?" There are multiple buttons with different descriptions. There are several working teams that may have the button, but it's possible that no one has it.
So, a user connects to our system and submits a form asking "who's got the button?" The form can describe the button by composition (plastic, bone, etc.), color, size, age, etc. (The user does his best to add enough detail.) Since there aren't too many buttons, sometimes just composition or age is sufficient for identification, but sometimes not. So, the request first goes to the user's supervisor (group) to validate that the request is valid and sufficient in detail (Human Task 1). The supervisor may reject the request for a number of reasons or approve it. If approved, an email is sent to all the teams (currently only 2) that might currently have the button. Here I split the workflow to two more human tasks. (I actually put these in an embedded sub-process.) For each of these team requests (human tasks), the response may be: "Not Me," "Need Additional Info (e.g. color)", or "Yes I have it." I recombined the workflow, but the answers are relevant to how the workflow procedes: If both answer "No," (happy path) the supervisor is notified, and the process completes. If neither answer "Yes," but at least one asks for additional information, the request is pushed back to the previous step. However, if one team answers "Yes," the process must complete and the other pending human task(s) must be cancelled (or completed) and the supervisor must be notified immediately and the process ends.
I hasven't even decided the best way to handle the "need more info" results. For right now, I need to know the correct way to cleanly end the other pending human tasks once one answers "yes."
I have tried quite a few different things such as events and errors, but nothing seems correct.
Any and all help is sincerely appreciated.
I'll resummarize the flow (code and image are not available):
- User submits request (start process)
- Supervisor approves or rejects (HT-1) (followed by xor gateway for decision flow)
- Diverge Gateway (AND)
- Simultaneously ask Team 1 and 2 (HT-2 & HT-3)
- Converge Gateway (AND) if results are No or Need More Info
- BUT if either HT response is Yes, other HT is immediately ended (cancelled or stopped), and the process continues
- Supervisor receives notification for subsequent action (HT-4)
John, what you could do (and you've already tried it) is to take advantage of using interrupting boundary events. I would see this as make your human tasks that are assigned to the teams (HT-2 and HT-3) signal aware. As boundary events attached directly to a task are not yet supported you need to use sub process for it. It will be simple sub process with only one task and interrupting signal boundary event attached to the sub process. Once a task is completed with Yes response you should throw a signal that corresponds to that boundary event and that will cause abort on the subprocess and its activities.
That is very helpful! But you lost me a bit with: "...only one task and interrupting signal boundary event attached to the sub process."
I created an embedded sub-process. In that sub-process is a start event, a diverge (AND) Gateway, splitting to the separate Human Tasks (HT) for each team, a converge (AND) Gateway, and a stop event. (This sub-process seemed logical, because I have several (currently only 2) teams making the same evaluation. I expect to add more teams eventually, but not soon.)
I noticed that the embedded sub-process Component has an Exception Handlers property, and so I tried to mimic "BPMN2-ErrorBoundaryEventInterrupting.bpm2" from the examples.
From here I got stuck. I couldn't get it to work at all, until I copied the Event naming exactly. Then I tracked some of the hard coded aspects down to the "org.jbpm.bpmn2.xml.ProcessHandler" class. It looks like my event types (and handling code) are limited/fixed. I suppose I can handle this as an Error, although it's really not.
From your reply, I think you are suggesting that I separately wrap HT-2 and HT-3 (from my example) in embedded sub-processes to make them "boundary aware." If that's correct, and I'm probably misunderstanding you, how would I make a "Yes" from HT-2 cause HT-3 to end (complete/cancel)?
I don't want to loose site of my goal, which is to have a "Yes" answer from one of the teams cause the other pending HT(s) to end immediately and the process to move on.
If I am on the right track with the sub-process I described, how should I raise the exception? It looks like I would have to use separate XOR Gateways to separate Error Events after each HT, and use separate Exception Handlers on the sub-process boundary, separate signal events, etc. Is that correct, or is there a cleaner, single handler, approach? Also, since one of the HTs did complete, how do I ensure that it's Result Mapping variables also propagate for down-process tasks to use?
I believe you got my idea quite good. Please find attached process diagram that I had in mind, note that I did not have time to make it runnable so number of things can go wrong, so to say.
In general, you have a sub process with mutliple instance chanracteristics so you can decide on runtime how many groups you will have, currently two and they are driven by some variables. This is just addition to have it ready for adding more teams without modifying the process.
Back to the main topic - yes you need to have a decision point after task is completed to decide if other intances (of a task/subprocess) should be cancelled or not. So if task will complete with Yes, it with throw an error (for now as it is avilable in current engine version and later on, can be changed to signal instead) that will be caught by all other active task/subprocess instances and cancel them and do what ever else is required.
Regarding data, isn\t that true that sub process on completion will map its variables to its parent variables?
I hope that it makes sense to you
I am using the Process Editor in eclipse and am having problems.
- The "Multiple Instances" Component does not have an "Exception Handlers" property. I thought that was where I would specify the handler for the "Yes" event. (the boundary event handler)
- When I create a "Multiple Instances" sub-process, exit, and reenter the editor, all of the components have large negative x & y locations. They aren't even visible. The "Multiple Instances" component becomes a scrolling pane, and I have to drag each embedded component back into position. I thought adding a UniqueId to the enclosing sub-process would help, but there's no MetaData property either.
- I'm using the Error Event to signal the Yes event, again, with no "Exception Handlers," but it looks like I can only use a Signal Event to continue the process outside the sub-process. There doesn't seem to be a "catch" version of the Error Event.
In short, I couldn't draw your diagram. Is there a better editor I should be using?
Hmn, but according to the BPMN2 spec (p 443) it seems that only "Terminate" and "Cancel" end events will terminate the subprocess:
For all other End Events, the behavior associated with the Event type is performed, e.g., the associated Message is sent for a Message End Event, the associated signal is sent for a signal End Event, and so on. The Sub-Process instance is then completed, if and only if the following two conditions hold:
All start nodes of the Sub-Process have been visited. More precisely, all Start Events have been triggered, and for all starting Event-Based Gateways, one of the associated Events has been triggered.
There is no token remaining within the Sub-Process instance.
Josh, in case we discussed sub process (or task) should not be terminated by end event but should be canceled (interrupted) by boundary event attached to it. As you can see, there are multiple instances of the sub process and if one of them completes with expected result it should throw a signal informing other sub process instances to interrupt their processing but this particular instance will be completed after event is thrown so no need to terminate itself. Does that make sense?
In my use case (see diagram in my previous reply), the several activities are not identical (e.g. a "multiple instance" subprocess doesn't really apply). Must I embed each of these choices in their own embedded subprocess, each throwing a signal event caught by the other subprocesses? Seems excessive, but I'm not sure how else to do it.