As you probably know if you have read this previous entry, Kogito supports Serverless Workflow Specification. This allows you to write a Kogito process definition using a JSON or YAML file.
Similar to a BPMN process, a Workflow can be understood as a state machine. In fact, a Workflow is defined by providing a set of states and the expected transitions between them.
This post explains how to handle errors that might occur while executing workflow states. States can do almost everything, from calling an external REST service to evaluating a JQ expression, and, although a non desirable situation, they might also fail. But don’t panic, the Workflow specification provides an error handling mechanism which allows users to deal with these circumstances .
Error Definition
An error is an exceptional occurrence that alters the regular Workflow execution sequence. When an error occurs, rather than transitioning to the state that would have been executed in case of a successful execution, the flow, if configured to do so, jumps instead to an alternative state, potentially capable of dealing with it. Note that error definition is always optional, if no error handling is defined, the Workflow execution will be aborted when something goes wrong.
Readers that are programmers will have already noticed that Workflow error handling has certain points in common with a try-catch construct (specially the unhandling scenario), but those that, like me, started programming with Sinclair Basic or Pascal, will have also appreciated the resemblance with the goto clause.
But, how does Kogito know which error should be taken into account? An Error definition in Serverless Workflow is composed of a name and an optional code. The name
is a natural language description of the error, for example: “wrong parameter”, while the code
is an optional, vendor specific parameter that helps the implementor to identify the error. In the case of Kogito, the code is the fully qualified java class name of an exception type that might be thrown by the action, for example: java.lang.IllegalArgumentException
.
Error Example
After this brief introduction, as usual the best way to illustrate the usage of this feature is through an example. This workflow accepts a number as input model and invokes checkEven
service, which throws an illegal argument exception if the number is odd. This means that if the number is even, as you can see in the diagram , flow will go to even
state, but if the number is odd, flow will move to odd
state, resulting in a different model output. Remember that an Inject state purpose is to populate the model with some specific json. finish
state is just printing the model, so the even state sets the message to be printed to “even” and the odd state consequently sets it to “odd” .
How is this achieved in the file definition? By populating the onErrors
field of checkEven
state with an array containing an error
definition. That error entry has a code
field that matches the exception thrown by checkEven
service (java.lang.IllegalArgumentException
) and a transition
field that points to the odd
state. Note that Kogito follows the same inheritance rules for exceptions as Java.
{
"error": "odd number",
"code": "java.lang.IllegalArgumentException",
"transition": "odd"
}
Conclusion
We have seen how to handle exceptions thrown by states in Serverless Workflow and forward them to other states capable of handling them. This allows users to execute subroutines to deal with known errors that might be triggered by external services rather than aborting the flow when such errors happen.