Lesson 2 of 7
Exception subprocesses
9 min
Listen to this lesson
An exception subprocess is the catch block of an integration flow. You add it from the palette (Process > Exception Subprocess) inside the integration process, without connecting it to any other step. When any step in that process throws, Cloud Integration stops the normal path and runs the subprocess instead. It always starts with an Error Start event. How it ends decides what monitoring, alerting and the sender see.
Three end events, three outcomes
| End event | Message status in monitoring | Use it when |
|---|---|---|
| End Message | Completed (optionally with a custom status) | You handled the error and want to reply to the sender with your own error message, or you parked the message on purpose |
| Error End | Failed | You added context to the log but the message really failed and must show as failed, for example so a JMS retry happens |
| Escalation End | Escalated | You want a failure that is searchable as its own status, separate from ordinary Failed messages |
Statuses per SAP's Handle Exceptions design guideline.
The End Message variant is powerful and dangerous. SAP's guideline uses it to send a friendly error back to an HTTP caller and set a different response code with the header CamelHttpResponseCode, plus the exchange property SAP_MessageProcessingLogCustomStatus (up to 40 alphanumeric characters) so the "completed but actually failed" messages can still be found with the Custom Status filter. Without a custom status, those messages look exactly like successes. One older note on the Define Exception Subprocess page says the log stays in an error state even when you catch the exception; the variant pages are explicit that End Message gives Completed, so confirm the behavior in your own test tenant before you rely on it.
Reading the caught exception
Inside the subprocess, the simple expressions ${exception.message} and ${exception.stacktrace} give you the error text in a Content Modifier. For more, use a Groovy script: the exchange property CamelExceptionCaught holds the exception object. SAP's script example for the HTTP receiver checks whether it is an org.apache.camel.component.ahc.AhcOperationFailedException and, if so, reads getStatusCode(), getStatusText() and getResponseBody(), so you know whether CMP said 503 or 400 and what it complained about.
The HTTP receiver adapter adds two options that change this picture. Throw Exception on Failure is on by default: an error response raises an exception and the subprocess runs. Switch it off and the flow continues; you route on ${header.CamelHttpResponseCode} yourself, as in SAP's "Don't Throw Exception on Failure" example. Timeouts, network and handshake failures still throw either way. Attach Error Details on Failure (on by default) stores request headers, response headers and response body as log attachments, which helps diagnosis but can store personal data (lesson 5).
Contoso keeps its classification in one place. The first Content Modifier in the subprocess copies ${exception.message}, ${property.SAP_ErrorModelStepID} and the Great Lakes PO number into exchange properties, so nothing is lost if a later step changes the body. A short Groovy script then reads CamelExceptionCaught, checks for a timeout or an HTTP status of 500 or above, and sets a property cmcErrorClass to TRANSIENT, PERMANENT or FUNCTIONAL. A Router branches on that one property. Keeping the decision in a single named value also makes it testable: every error-path test in lesson 7 states which value it expects.
- Error StartThe subprocess starts on any exception in its process.
- Capture contextContent Modifier copies ${exception.message}, the order number and SAP_ErrorModelStepID into properties.
- ClassifyA Router or script decides: functional, transient or permanent.
- ActCall the shared handler through ProcessDirect, park the message, or forward to AIF.
- End deliberatelyError End for retry or visible failure; End Message only with a custom status.
Limits you will hit
- An exception subprocess cannot contain another exception subprocess, a local integration process, sender or receiver participants, a Splitter or an Aggregator (check the current list on the Define Exception Subprocess page).
- A Data Store Write that fails with a duplicate key cannot be handled by the subprocess: the database transaction is rolled back even if one exists. Prevent that case with Overwrite Existing Message or a prior Get.
- Once the subprocess runs, normal processing ends. It does not resume the main path where the error happened.
- Branching steps such as Multicast and Splitter change how far an error travels; force an error in each branch in the test tenant before you rely on the subprocess catching it.
Local integration processes and ProcessDirect
A local integration process is a subprocess you call with a Process Call step. SAP's documentation says you cannot catch its exceptions in the main process, so put an exception subprocess inside the local process itself. SAP's reference flow "Handle Errors - Local Integration Process" shows the effect: the local process ends with Error End, its exception subprocess builds the error response, and the steps after the Process Call in the main process do not run. A local process may not contain an End Message event.
Across flows, Cloud Integration's ProcessDirect adapter connects integration flows in the same tenant. Contoso uses it in two ways. Every exception subprocess calls CMC_Common_ErrorHandler at ProcessDirect address /cmc/common/error, so logging, custom status and AIF forwarding are built once. And in a parent/child design, SAP's guideline for dependent flows shows the child ending its exception subprocess with an End Message and setting a header (in SAP's example error_occured) that tells the parent to take its error route, so one failed item does not fail the whole batch.
- Exception subprocess: Error Start, then End Message (Completed), Error End (Failed) or Escalation End (Escalated).
- End Message hides failures unless you set SAP_MessageProcessingLogCustomStatus.
- Read errors with ${exception.message}, ${exception.stacktrace} or the CamelExceptionCaught property in a script.
- With Throw Exception on Failure off, route on CamelHttpResponseCode; timeouts still throw.
- Handle local process errors inside the local process; share handlers across flows with ProcessDirect.
Check your understanding · not graded
Lesson check
1. An exception subprocess ends with an Escalation End event. What status does the message get?
2. Why should an exception subprocess that ends with End Message set a custom status?
3. In a Groovy script inside the exception subprocess, where do you find the exception object?
4. A Data Store Write fails because the entry ID already exists. What happens with the exception subprocess?