Pages

Monday, December 7, 2009

A custom jBPM exception framework for jBPM 3.x

I have spent some time over the last few months (slowly, only one day a week) working on a jBPM exception handling framework. I wanted to present the use case and leave the exact details over to you as an exercise in Java coding. ;-)

The idea is that jBPM (here using 3.x supported versions from the Red Hat JBoss Customer Support Portal (CSP) provides the standard jBPM exception and that I want to also have the choice to apply a dynamically generated transition from the point of an exception that takes me to a custom exception flow. This custom exception flow is nothing more than a single decision that, based on the type of exception I have passed, will choose a path to one of the following:

task node (human task to evaluate the exception)

state node (retry using a timer to wait a bit before trying again)

any eventual node desired to process the exception

There are some fairly obvious benifits:

no longer just one handling for all your jBPM process exceptions

very extensible, just add new nodes into the exception handling process flow to provide new functionality

placing exception handling into an apart flow means you can deploy this once and use it with all of your deployed processes

provides for decisions, states and node exception handling. Transitions should not be doing anything exciting within my processes, if yours needs to you can extend this concept to these too.

The process flow diagram provided in this post shows the simple testing framework I used to enable this. All code snippets shown are simplified for this post. There is a global attribute that is checked for using our custom exception framework called 'useCustomExceptions'.

Decisions
For a decision node we need to implement the DecisionHandler from jBPM, so I do that in an AbstractDecisionHanlder that implements the decide() method and puts in an extra handleException() method as follows:

Node
For a node we need to implement the ActionHandler from jBPM, so I do that in an AbstractActionHanlder that implements the execute() method. Furthermore I need to come up with a solution for the following issue that is unique to the jBPM 3.x node. When you enter a node, you have an on-node-enter event and when finished it will trigger the on-node-leave event which takes the transition that is assigned during the event on-node-enter event. This means using the Node.leave(some-transition) method will not work.

I got the reaction when I used this Node.leave(take-dynamic-transition-to-exception-handling) it worked fine until it entered the human-task wait state. At this point the originating node then continued onwards, taking the default transition (that was in the TransitionsList for the node) and merrily finishing the process flow. Even stranger, this was done on the same process id that was also assigned to some human task!

My solution is to provide a mechanism to do the following:

create the dynamic transition to custom exception handling for the node

add the dynamic transition to the TransistionsList for this node

put a copy of the TransistionList (without the new dynamic transition) into the jBPM Context

remove all transition entries from the TransistionsList except for the new dynamic one

use Node.leave() to follow the new dynamic transition

deal with exception handling

upon returning to the node after exception handling, pick up the transitions from the jBPM Context

fill the TransitionsList with those found in the jBPM Context

use Node.leave() to use the default

Some code to give you an idea with migrateTransitionsInNodeToContext which shows the transitions being migrated into the jBPM Context. I have left out the recovery of the transitions from the context, as it is trivial to reverse the process. To give you a bit of a hint, when you are in the exception handling process and decide it is time to go back to your originating node, you create a dynamic transition and fill the originating nodes TransitionsList from the jBPM Context. Here is some code snippets: