Ending the message the right way!
Earlier this week, I was adding new functionality to exception handling. This change was to End the Message with an Escalation End Event instead of an End Message Event to enable filtering the error message using the status field for Monitoring. In this article, I would like to share an interesting finding I stumbled across while implementing this functionality.
Let’s start with As-Is design, this flow picks up messages from a JMS queue and checks if the current retry count is less than the maximum retries configured in the flow. If yes, messages are forwarded to ProcessDirect Adapter for further processing. ProcessDirect Adapter is set dynamically from a header (custom header ReceiverAddress in this case). If there is an exception in the receiver flow, the message will be sent back to JMS. If the current retry count is higher or equal to the maximum retries configured in the flow, then a custom status is set and the message processing ends with End Message Event.
Drawbacks of As-Is Design
The As-Is design lacked support for monitoring.
Firstly, the message is ended with Completed status in all cases. This results in insufficient attention to the errors especially for the messages that have failed with maximum retries.
Secondly, the errored messages are difficult to find. There is a workaround of setting the custom status on final retry and filtering using the Custom Status field. A related disadvantage is that we cannot create a tile filtered on custom status in the landing page of the Monitoring.
Thirdly, if the error has occurred in the receiver system, then the receiver system may respond with error details. These error details or response payload is lost as the check for the number of retries exceeding maximum retries is the first step after fetching the message from the queue.
To-Be Design (with mistake)
In To-Be design, the message is picked up from the queue and redirected to the ProcessDirect Adapter in the first step. If the receiver flow throws an exception, the Exception Subprocess is triggered which, in turn, invokes the Local Integration Process.
In Handle Exception Local Integration Process, if the current retry count is less than the maximum retries configured in the flow, then the Local Integration Process ends with End Event returning the control to the calling process. The calling process ends with an Error End Event. As a result, the message is put back into the queue.
If the number of retries is greater than or equal to the maximum retries configured in the flow, then the custom status is set, the exception message is set as body, and the message is persisted. This path ends with an Escalation End Event.
The To-Be Design overcomes all three drawbacks of the As-Is Design.
When the message is retried maximum times and fails, the message is ended with an Escalated status. As a result, the message can be easily filtered using the status filter in the Monitoring. In the landing page of the Monitoring, we can create a tile for the number of messages in Escalated status. Persisting the exception message facilitates diagnostics.
The mistake in the To-Be Design is the combination of ending with Escalation End Event in Local Integration Process and ending with Error End Event in the invoking process. The behaviour of Escalation End Event is as follows:
Local integration process:
If an integration process is calling a local integration process and an escalation event has been defined in the local integration process, the Escalation Event is thrown, and the processing continues in the calling flow. If there are still steps to process in the main flow, the processing continues normally at this level and the main flow message status will be Completed.
When the message is tried maximum times and fails, it ends with an Escalation End Event and returns the control to invoking process. In the calling/main process, the message ends with an Error End Event. As a result, the message is put back into queue even after maximum retries have been attempted. This is undesired behaviour.
To-Be Design (Corrected)
In the corrected design, Exception Subprocess ends with End Message Event instead of Error End Event and the Local Integration Process uses Error End Event to trigger retry instead of using End Event.
With these two changes, everything works as intended.
When the message processing is ended with an Escalation End Event in a Local Integration Process, the processing continues in the parent process. Ensure that you handle the next steps appropriately in the parent process after invoking the Local Integration Process that may end with an Escalation End Event. In the example, the appropriate step was simply an End Message Event.
These are a few cool things about the To-Be solution that can be reused elsewhere:
- Custom status can be set using the exchange property SAP_MessageProcessingLogCustomStatus.
- When the message ends with Failed status, payloads stored using Persist step are not available. To overcome this limitation, Escalation End Event can be used.
- When the message is fetched from the JMS for retry, it doesn’t have information about the previous run. Therefore, it is better to decide whether to retry the message or not in the Exception Subprocess instead of checking it as a first step. Examples of the error information is available in the comment below.
- On the Monitoring Landing Page, a tile can be created by filtering on status, duration, and artefact.
- Escalation End Event Behaviour
- Cloud Integration Components
Hope this helps,