Loadingβ¦
Build one integration flow that takes a customer order in XML, stamps it with context, reads values out of the payload, and answers the caller with a JSON acknowledgement β using nothing but Content Modifier steps.
If you only ever learn one step in SAP Cloud Integration, learn this one. The Content Modifier is how you write to the message as it passes through the flow β and nearly every iFlow you will ever open has several of them.
Think of a message travelling through an iFlow as three things carried together:
The Content Modifier is the one step that writes to all three, and it has a tab for each. That is the whole idea. Everything else β constants, XPath expressions, timestamps β is just where the value comes from.
The rule that catches everyone: the Message Body tab replaces the payload entirely. It is not an edit. If you only want to add a header, do not touch that tab at all β whatever you type there becomes the whole message.
In this lab you will use three of them in a row: one to stamp the message with constants, one to read values out of an XML order with XPath, and one to build a JSON reply from what you read. By the end you will know which of the three destinations to reach for without thinking about it, which is the difference between copying an iFlow and understanding one.
There is no receiver system in this lab. An HTTPS sender with no receiver returns the final body straight back to the caller β so whatever your last Content Modifier writes is what you see in Postman. Every mistake is visible in one second.
The one idea behind all of it. A CPI message carries three separate things: headers (travel out to the receiver), properties (live only inside the flow), and the body (the payload). The Content Modifier is the one step that writes all three β one tab each.
| Item | Why |
|---|---|
| An SAP BTP / CPI trial tenant | To create the package, iFlow and deploy it. A free trial is enough. |
The role ESBMessaging.send | Assigned to your test user, or the endpoint answers 401. |
| Postman (or any HTTP client) | To POST the test payload and read the response. |
| ~90 minutes | Deploy and test after every task β that habit is half the lab. |
Training_ContentModifier_XX.Order_Enrichment_CM./order-enrich-XX, Authorization User Role with ESBMessaging.send.Trace. Save, then Deploy.Content-Type: application/xml. You should get HTTP 200 and your own XML echoed back. A 401 means the role is missing; a 404 means the flow is not started.Learn the simplest thing a Content Modifier does β write a fixed value that was never in the payload β and learn how to see that it worked.
CM_SetContext.| Name | Source Type | Source Value |
|---|---|---|
| SourceSystem | Constant | WEBSHOP |
| InterfaceId | Constant | INT-0042 |
| ProcessedBy | Constant | your full name |
CM_SetContext and switch the pane between Header, Property and Payload. All three headers must be listed.Deliverable. A screenshot of the Trace header pane showing all three names and values.
Learn the header-versus-property decision, and write your first value calculated at runtime instead of typed by hand.
| Name | Source Type | Source Value |
|---|---|---|
| ProcessingStatus | Constant | ACCEPTED |
| ReceivedAt | Expression | ${date:now:yyyy-MM-dd'T'HH:mm:ss} |
Write it down · 5 of 20 marks. In two sentences: why does ReceivedAt belong in a property rather than a header? Say what happens to each when the message leaves through a receiver adapter.
Learn the Content Modifier's most-used trick: lifting fields out of an XML body so you can use them later without touching the payload again.
| Name | Type | Data Type | XPath |
|---|---|---|---|
| OrderNumber | XPath | java.lang.String | /Order/Header/OrderNumber |
| CustomerId | XPath | java.lang.String | /Order/Header/CustomerId |
| Currency | XPath | java.lang.String | /Order/Header/Currency |
CM_ReadOrder → Property pane shows real values. Empty values almost always mean a wrong path or a missing Data Type β not a broken tenant.Write a completely new body out of values you collected earlier β and see that the Message Body tab replaces the payload rather than editing it.
{
"acknowledgement": {
"orderNumber": "${property.OrderNumber}",
"customerId": "${property.CustomerId}",
"sourceSystem":"${header.SourceSystem}",
"receivedAt": "${property.ReceivedAt}",
"status": "${property.ProcessingStatus}"
}
}${property.OrderNumber} means a misspelled name, or the value was stored as a header instead of a property.Externalized parameters β the reason real projects move the same iFlow from DEV to QA to PROD without opening the editor.
Two things beginners expect and don't find. There is no "External Parameter" in the Source Type list β externalizing is the Externalize link at the top-right of the step. And the Source Value there holds the parameter name, not the value β it comes back as {{EnvName}}.
EnvName from DEV to QA via Configure only β never reopening the editor β and the same flow answers "environment": "QA".${header.X} will not find a property.Trace and keeps data about ten minutes.${property.Currency}. Two likely causes?Tick these off as you go β this page remembers your ticks.
<Order>
<Header>
<OrderNumber>SO-100234</OrderNumber>
<CustomerId>CUST-8891</CustomerId>
<Currency>EUR</Currency>
</Header>
</Order>SAP Help β search "Define Content Modifier" for the official field reference.
Ask a question, share your iFlow, or help someone one task behind you.