Error handling in SonataFlow
This document describes how you can handle the errors that might occur in SonataFlow.
The Serverless Workflow specification provides an error handling mechanism, enabling you to handle the errors that might happen during the interactions between the workflow and external systems.
When an error occurs, it changes the regular workflow sequence. In such cases, a workflow state transitions to an alternative state that can potentially handle the error, instead of transitioning to the predefined state.
Note that error definition for a workflow is optional. If error handling is not defined, then the workflow execution is aborted when an error occurs. As a developer, you can consider the error handling in SonataFlow as a try-catch
or a goto
construct.
Error definition
An error definition in a workflow is composed of a name
and code
parameters. The name
is a short and natural language description of an error, such as wrong parameter
. The code
parameter helps the implementation to identify the error.
The code
parameter is mandatory and the engine uses different strategies to map the provided value to an exception encountered at runtime. The available strategies include fully qualified class name, error message, and status code.
- Fully Qualified Class Name (FQCN)
-
You can define the mapping as the fully qualified Java class name of an exception type.
To determine if an exception is handled by an error definition, a workflow first checks whether or not the type of the Java exception is an instance of the exception that is specified in the error definition. Otherwise, the workflow recursively applies the same check to any embedded exception within the original Java one, till the exception chain is exhausted.
Table 1. Runtime exception examples: Runtime exception Error code definition java.lang.RuntimeException
java.lang.RuntimeException
java.lang.IllegalStateException
java.lang.RuntimeException
- Error message
-
You can define the mapping as a partial match of the error message using regex patterns.
A workflow verifies whether the message of the Java exception matches the value provided in the error
code
. The validation is performed using a regex matcher. The validation is successful if a partial match is found. Note that the validation is performed in a case-sensitive manner. If case-insensitive pattern matching is desired, use the embedded flag expression(?i)
within the regular expression.Table 2. Error message examples: Error message of runtime exception Error code definition Unknown error, status code 400
Unknown error
Unknown error, status code 400
(?i)Error
orerror
Unknown error, status code 400
(.*)status code 4[0-9]{2}
orstatus code 4[0-9]{2}
- Status code
-
You can define the mapping as a status code returned by the invoked service.
The external services return status codes in the event of a failure. For example, HTTP status codes are returned by REST or OpenAPI service invocations. In this case, the workflow verifies the defined error code against the HTTP code from the underlying response object.
You can define the error code either as an HTTP code or as a colon-separated string, in which the error definition contains the error code in the last part.
Table 3. Status code examples: HTTP status code Error code definition 400
400
400
HTTP:400
Example of error handling
The workflow in the serverless-workflow-error-quarkus
example application illustrate the usage of the error handling mechanism.
The workflow accepts an integer number as the input model. When the workflow starts, it invokes the isEven
Java service, which accepts that integer number as a parameter. This service throws an IllegalArgumentException
exception if the integer number is odd. This means that if the integer number is even, the workflow transitions to the even
state, however, if the integer number is odd, the workflow transitions to the odd
state, resulting in a different model output.
checkEven
state{
"name": "checkEven",
"type": "operation",
"actions": [
{
"name": "checkEvenAction",
"functionRef": {
"refName": "isEven",
"arguments": {
"number": "$.number"
}
}
}
],
"transition": "even",
"onErrors": [
{
"errorRef": "odd number",
"transition": "odd"
}
]
}
The workflow defines a function that invokes the isEven
method of org.kie.kogito.examples.EvenService
class. This function uses a custom function type, enabling SonataFlow to invoke Java methods.
isEven
function definition{
"name": "isEven",
"type": "custom",
"operation": "service:java:org.kie.kogito.examples.EvenService::isEven"
}
To handle the error, the workflow defines an odd number
error which handles any runtime exception. As the IllegalArgumentException
is a child of RuntimeException
, if isEven
method throws the exception, it will be handled.
"errors": [
{
"name": "odd number",
"code": "java.lang.RuntimeException"
}
]
The Inject state is used to populate the model with specific JSON payload. Therefore, the even and odd state defines the message
property as even
and odd
respectively.
{
"name": "even",
"type": "inject",
"data": {
"numberType": "even"
},
"transition": "finish"
},
{
"name": "odd",
"type": "inject",
"data": {
"numberType": "odd"
},
"transition": "finish"
}
The finish
state in the serverless-workflow-error-quarkus
example application displays the model content to the console, so you can verify that the expected message has been set.
{
"name": "finish",
"type": "operation",
"actions": [
{
"name": "printAction",
"functionRef": {
"refName": "printMessage",
"arguments": {
"message": "$.numberType"
}
}
}
],
"end": {
"terminate": "true"
}
}
Found an issue?
If you find an issue or any misleading information, please feel free to report it here. We really appreciate it!