Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 1 of 7

Designing for failure

10 min

Listen to this lesson

0:00 / 6:35

Every integration flow fails sometimes. A receiver restarts, a certificate expires, a partner sends a part number nobody has mapped. The question is not whether your flow will meet an error but what it does next: retry quietly, stop and tell a person, or reject the message back to the sender. A flow without a deliberate answer still has one. It is just the default, and the default is rarely the right one for the business.

This course follows one Contoso Motor Co. interface from design to test. Great Lakes Fleet Services sends depot replenishment orders to Contoso as JSON over HTTPS (its headquarters purchase orders still arrive as X12 850 EDI, covered in sap-pim-206). Theo, the integration lead, has split the interface into two integration flows in SAP Cloud Integration, the integration service of SAP Integration Suite: CMC_GLFS_Order_Receive accepts the order, checks it and writes it to the JMS queue CMC_GLFS_ORDERS; CMC_GLFS_Order_Deliver reads the queue, maps the order to an ORDERS05 IDoc and posts it to the production system CMP through SAP Cloud Connector. The order that became sales order 1000473 travelled this path. The operations side (monitoring maps, ownership, reprocessing and reconciliation) is covered in sap-int-205; this course is the developer's half.

Contoso splits receipt from delivery with a JMS queue, so a CMP outage never reaches Great Lakes Fleet Services as an error.
The Sign-Off Table · thesignofftable.com/academy/sap-pim-207

Three kinds of error

Before you draw an exception subprocess, sort the errors your flow can meet into classes, because each class needs a different response. The useful split is by what fixes the error.

ClassExample at ContosoWhat fixes itRight response
Transient technicalCMP or Cloud Connector does not answer within the timeout during a restartTime. The same message succeeds later.Retry automatically with backoff; alert only if retries run out
Permanent technicalExpired client certificate, wrong credentials, a mapping that throws on every messageA developer or Basis fixStop retrying fast, alert the integration team, keep the message
Functional (business)Great Lakes sends part number GLF-ALT-24X, which has no mapping to a Contoso materialMaster data or a business decisionDo not retry; route to the business owner with the order context

Classify by what fixes the error, not by where it was thrown.

The trap is treating every error the same way. A flow that retries a functional error retries it forever: the unknown part number will be unknown on the fortieth attempt too, and meanwhile the queue fills and the alert inbox drowns. A flow that sends every transient timeout to a person creates hundreds of tickets for problems that would have healed themselves in two minutes. sap-int-205 routes each error to the person who can fix it; here you build the flow so it can tell the classes apart in the first place.

Transient, singleOne order hits a CMP timeout. Retry it; nobody needs to know.
Functional, singleOne order has an unmapped part. Park it and tell Maria.
Transient, allCMP is down for an hour. Retry with backoff; alert if it lasts.
Permanent, allA certificate expired. Every message fails; alert Theo now.
Plot each error by what fixes it and how many messages it hits; each quadrant gets its own response.
The Sign-Off Table · thesignofftable.com/academy/sap-pim-207

Where the class is known

You can only classify an error where you have the information. Cloud Integration gives you three signals. The step that failed: the exchange property SAP_ErrorModelStepID holds the ID of the step where the error occurred, which you can see under Technical Information on a selected shape. The exception itself: its text and Java class. And for HTTP calls, the response code the receiver returned. A 503 or a timeout says "try later"; a 400 with a validation message says "this message is wrong".

Functional errors you detect yourself are the easiest to classify. In CMC_GLFS_Order_Deliver, a value mapping turns the customer's part number into a Contoso material. If no mapping exists, a Router sends the message to an Error End event in the main process with a clear reason. That deliberate error carries its own step ID, so the exception subprocess can recognize it and route it differently from a timeout. SAP's reference flow for this pattern (Pattern Content Based Routing, Raise Error) routes on ${property.SAP_ErrorModelStepID} in exactly this way.

Contoso classifies in this order: its own business errors first, then receiver responses, then everything else as permanent.
The Sign-Off Table · thesignofftable.com/academy/sap-pim-207

Synchronous or asynchronous decides your options

Your design choices depend on who is waiting. If the sender waits for an answer (a synchronous HTTP or SOAP call), the flow cannot retry for an hour; it must answer within the caller's timeout, so the best you can do is a clean, meaningful error response and perhaps a short in-call retry. If nobody waits, persist the message first and process it asynchronously. That is why CMC_GLFS_Order_Receive does almost nothing: it validates the JSON, writes to the queue and answers Great Lakes with HTTP 202 Accepted. SAP's design guideline "Apply the Retry Pattern with JMS Queue" describes exactly this split.

What would you do?

Great Lakes Fleet Services complains that orders sometimes take three hours to appear in CMP, and once an order never arrived. Theo finds that <code>CMC_GLFS_Order_Deliver</code> has one exception subprocess that sends an email for every error. What should he change first?

Key points
  • Classify errors by what fixes them: time (transient), a technical fix (permanent) or a business decision (functional).
  • Retry only transient errors; functional errors fail the same way every time.
  • Use the failed step ID, the exception and the HTTP response code to tell classes apart.
  • Raise your own functional errors deliberately with an Error End event, so they are easy to recognize.
  • If nobody waits, persist first and process asynchronously; that is what makes retries possible.

Check your understanding · not graded

Lesson check

  1. 1. An order fails because the customer part number has no value mapping. Which response fits?

  2. 2. Which exchange property holds the ID of the step where an error occurred?

  3. 3. Why does CMC_GLFS_Order_Receive answer Great Lakes with HTTP 202 after writing to a queue?

  4. 4. A client certificate for CMP has expired. Which class is this, and what should happen?