October 24, 2026

Day-to-day challenges in SAP Cloud Platform Integration (CPI)

SAP Integration Suite / CPI

SAP CPI / Integration Suite

30 Advanced Interview Scenarios & Solutions

A comprehensive guide for Medium to Advanced level professionals

Architecture & Core Concepts

Scenario 1: You need to integrate an SAP system with a third-party application, but the third-party application frequently goes offline for maintenance. How do you design the IFlow to ensure zero message loss?

Solution: To ensure zero message loss (guaranteed delivery), I would implement an asynchronous decoupling pattern using JMS (Java Message Service) queues. The sender would send the message to CPI, which immediately writes it to a JMS queue and returns a 200 OK to the sender. A second Integration Process would read from this JMS queue and attempt to send the payload to the third-party receiver. If the receiver is offline, the JMS adapter's built-in retry mechanism will automatically attempt redelivery based on the configured exponential backoff parameters until the system is back online.

Scenario 2: Your integration flow processes large files (e.g., 500 MB) from an SFTP server. The flow frequently crashes with OutOfMemory (OOM) errors. How do you resolve this?

Solution: To handle large payloads, we must avoid loading the entire file into memory (DOM parsing). I would use the General Splitter or Iterating Splitter with 'Streaming' enabled to process the file in chunks. Alternatively, if the file is a large CSV, I would read it line-by-line using the Iterating Splitter. Additionally, I would ensure that no 'Trace' mode is turned on in production and avoid using Content Modifiers to store the entire payload as an exchange property, as properties reside in memory.

Scenario 3: You have a requirement where an incoming payload contains orders for multiple different regions (US, EMEA, APAC). Each region must be processed differently and sent to a different target system. How do you architect this?

Solution: I would use a Multicast step (or Splitter if the regions are in a list) combined with a ProcessDirect adapter. First, I would route the message based on the region node using an XPath expression in a Router. Then, instead of building massive, complex logic in a single IFlow, I would send the region-specific payload to a ProcessDirect receiver. Different child IFlows would consume these ProcessDirect calls, allowing modularization, independent deployment, and easier maintenance.

Scenario 4: Two independent Integration Flows (IFlow A and IFlow B) need to share a small piece of reference data, such as a daily exchange rate or a token. How can you achieve this state sharing?

Solution: CPI is generally stateless across different IFlows. To share state, we can use Global Variables (Write Variables / Read Variables). IFlow A can fetch the token or exchange rate and write it to a Global Variable. IFlow B can then read this Global Variable. Alternatively, if the data is slightly larger, a Data Store operation could be used. Both mechanisms persist data in the tenant's database, making it accessible across all IFlows in the same tenant.

Scenario 5: You need to implement an 'Exactly Once' (Idempotent) scenario. The sender system might send the same invoice twice due to network glitches, but the receiver ERP system cannot handle duplicate invoices. How do you handle this in CPI?

Solution: I would use the Idempotent Process Call pattern in CPI. I would extract a unique identifier from the incoming payload (e.g., InvoiceNumber) and pass it to the Idempotent Process Call step. CPI will store this ID in its database. If a subsequent message arrives with the same InvoiceNumber, CPI will detect the duplicate. I can configure it to either skip the processing entirely or return the cached response of the original execution to the sender.

Scenario 6: What is the difference between a Content Enricher and a Poll Enricher, and when would you use each?

Solution: A Content Enricher is used to make a synchronous call to an external system (via HTTP, OData, SOAP) in the middle of an IFlow to fetch additional data and merge it with the original payload. A Poll Enricher, on the other hand, is specifically used to poll a file from an SFTP server in the middle of a process. I would use the Content Enricher to fetch a customer name from an OData API using a Customer ID, and the Poll Enricher if I need to read a static lookup CSV file located on an SFTP server during execution.

Error Handling & Reliability

Scenario 7: When an error occurs in an IFlow, you need to send an email alert containing the original incoming payload, not the payload at the time of failure. How do you implement this?

Solution: In CPI, payloads change as they pass through mapping and modifier steps. To preserve the original payload for error handling, I would save the incoming body as an Exchange Property in the very first step (Content Modifier). Then, I would add an Exception Subprocess to the IFlow. Inside the Exception Subprocess, I would use a Content Modifier to replace the current body (which might be in a failed, half-mapped state) with the original payload saved in the property, and then route it to the Mail adapter.

Scenario 8: A receiver system throws a temporary HTTP 503 (Service Unavailable) error. You want your IFlow to retry up to 3 times before failing completely. How do you design this?

Solution: For synchronous HTTP calls without JMS, I would use a Loop Process Call configured to iterate up to 3 times. Inside the loop, I would wrap the Request-Reply step in a Local Integration Process with an Exception Subprocess. If a 503 occurs, the Exception Subprocess catches it, increments a retry counter, and adds a Delay step (via Groovy). If the call succeeds, a flag is set to exit the loop. If it fails after 3 times, an error is formally thrown.

Scenario 9: How do you differentiate between business exceptions (e.g., invalid data) and technical exceptions (e.g., connection timeout) in CPI's Exception Subprocess?

Solution: Inside the Exception Subprocess, I would use a Groovy script to inspect the CamelExceptionCaught property. Technical errors (like java.net.ConnectException or HTTP 401) can be identified by their exception class or HTTP status codes. Business errors often return a 400 Bad Request or a specific XML/JSON error payload from the target. I would route the message based on these conditions: technical errors might trigger an alert to the IT team, while business errors might trigger an email back to the data sender.

Scenario 10: You have an IFlow using a JMS adapter for retries. However, you notice that a 'Poison Message' (a message that always fails due to invalid data format) is endlessly retrying, clogging the JMS queue. How do you handle poison messages?

Solution: I would configure a Dead Letter Queue (DLQ) mechanism. In the JMS adapter settings, there is a parameter for 'Maximum Retries' or 'Exponential Backoff' limits. Once the retry limit is reached, the message should be moved to a DLQ or an error queue. Alternatively, in an Exception Subprocess, I can check if the failure is a parsing/mapping error (which will never succeed on retry) and intentionally end the process gracefully (or send to an error data store) instead of throwing an unhandled exception back to the JMS queue.

Advanced Groovy Scripting & Data Transformation

Scenario 11: You need to parse a complex JSON structure in Groovy, modify a specific nested field, and output it back as JSON. Which Groovy libraries do you use?

Solution: I would use Groovy's built-in JsonSlurper to parse the incoming JSON string into a Groovy Map/List object. Then, I would traverse the object (e.g., parsedJson.header.details[0].status = 'Completed') to modify the necessary fields. Finally, I would use JsonOutput.toJson(parsedJson) to convert the modified object back into a JSON string and set it as the message body. This avoids using heavy standard converters for simple field updates.

Scenario 12: An external API requires a dynamic header X-Signature which is an HMAC-SHA256 hash of the payload and a secret key. How do you generate this in CPI?

Solution: I would use a Groovy script to generate the HMAC-SHA256 hash. First, I would retrieve the secret key from the CPI Keystore or Secure Parameters using the ITApiFactory. Then, I would read the message body as a String, and use Java's javax.crypto.Mac and javax.crypto.spec.SecretKeySpec classes to generate the hash. I would encode the resulting byte array using Base64 (java.util.Base64), and finally set it as a message header (message.setHeader('X-Signature', hashValue)).

Scenario 13: Your standard message mapping fails because the incoming XML has an unpredictable namespace prefix, or sometimes lacks a namespace entirely. How do you make the mapping robust?

Solution: Standard SAP CPI message mapping is strictly bound to the namespaces defined in the XSD. To make it resilient, I would place a Groovy script or an XSLT mapping before the Message Mapping step to strip or normalize the namespaces. Using a simple XSLT script with local-name() can completely remove namespaces from the incoming XML, allowing the Message Mapping to rely solely on the structure, or I can use an XML Modifier step to remove namespaces.

Scenario 14: You need to fetch a confidential API Key (e.g., 'Stripe-API-Key') securely without hardcoding it in a Content Modifier. How is this done?

Solution: I would store the API key as a 'Secure Parameter' in the CPI Security Material. In the IFlow, I would use a Groovy script to access the Secure Store service. I would use the ITApiFactory.getApi(SecureStoreService.class, null) method, retrieve the credential object by its alias name, and extract the password/key. Then, I can set it as an HTTP header directly in the script for the subsequent outbound call.

Scenario 15: How do you read an attachment (e.g., a PDF file) sent via a SOAP request and send it to an SFTP server?

Solution: In a Groovy script, I would access the attachments using message.getAttachments(). I would iterate through the map of attachments, get the DataHandler or InputStream of the PDF, and set it as the main message body (message.setBody(attachment.getContent())). I would also capture the attachment's filename and set it as the CamelFileName header. Then, the message can be routed to the SFTP receiver adapter which will write the body as a file.

Scenario 16: You need to perform a dynamic lookup based on a target system name at runtime. The routing rules are maintained in a Value Mapping. How do you access Value Mappings inside Groovy?

Solution: I can access Value Mappings programmatically in Groovy using the ITApiFactory. I would get the ValueMappingApi, then call getMappedValue(sourceAgency, sourceIdentifier, sourceValue, targetAgency, targetIdentifier). This allows me to pass a dynamic source value from the payload and retrieve the target system name, which I can then set in a header to dynamically configure the ProcessDirect or HTTP adapter URL.

Security, Connectivity & Adapters

Scenario 17: You are connecting to an on-premise SAP S/4HANA system using the Cloud Connector. The S/4HANA system requires 'Principal Propagation' so that the original cloud user's identity is maintained. How do you configure this?

Solution: First, the SAP Cloud Connector (SCC) must be configured for Principal Propagation (trusting the BTP subaccount and mapping cloud users to ABAP users via short-lived certificates). In the CPI IFlow, I would use an HTTP or OData adapter, set the Proxy Type to 'On-Premise' to route traffic through the SCC. Then, I would set the Authentication type to 'Principal Propagation'. CPI will pass the user context (from the inbound JWT token) to the SCC, which forwards it to S/4HANA.

Scenario 18: A third-party webhook pushes JSON data to your CPI HTTP endpoint. How do you secure this inbound endpoint using OAuth 2.0?

Solution: I would configure the inbound HTTP adapter's Authorization to 'Role Based' (e.g., ESBMessaging.send). In the SAP BTP Cockpit, I would create a Service Instance of the Process Integration Runtime service with the plan 'integration-flow'. I would then create a Service Key for this instance. This Service Key generates a Client ID, Client Secret, and a Token URL. The third-party system must first call the Token URL to get a Bearer JWT, and then pass that token in the Authorization header to call the CPI endpoint.

Scenario 19: You are extracting delta employee records from SuccessFactors. How do you configure the SuccessFactors adapter to ensure it only pulls records modified since the last successful run?

Solution: I would use the SuccessFactors (OData or SOAP Compound Employee) adapter. For OData, I would use the $filter query parameter on the lastModifiedDateTime field. However, to maintain the delta state across runs, I would utilize CPI's built-in 'Data Store / Variables' or simply use the built-in 'Query Options' in the adapter where I can define a dynamic time-based filter using ${date:now...} or standard Delta Sync features available in the SuccessFactors OData V2 adapter, which automatically manages the watermark.

Scenario 20: The target system requires an OAuth2.0 'Authorization Code' grant type, which involves user interaction. Can CPI handle this natively, and if not, what is the workaround?

Solution: CPI is a middleware designed for system-to-system integration, so it natively supports the 'Client Credentials' grant type via the OAuth2 Credentials artifact. It cannot handle the 'Authorization Code' grant (which requires a browser redirect for user login). To work around this, a separate application or manual process must generate the initial Access Token and Refresh Token. CPI can then securely store the Refresh Token and use a Groovy script to call the token endpoint to get a new Access Token whenever the current one expires.

Scenario 21: You need to send an encrypted file to a bank using PGP. What artifacts do you need to configure in CPI?

Solution: I need the Bank's PGP Public Key. I would upload this Public Key into the CPI PGP Public Key Ring using the Keystore monitor. In the IFlow, I would use the PGP Encryptor step. In the step configuration, I would specify the encryption algorithm, the signer (if signing is required, which needs our Private Key), and the Public Key alias of the bank to encrypt the payload before routing it to the SFTP receiver.

Scenario 22: You are making an HTTP call to a REST API. The API responds with a 404 Not Found or 400 Bad Request. By default, the CPI HTTP adapter throws an exception and stops the flow. How do you capture the HTTP body of the error response?

Solution: In the HTTP receiver adapter, there is a setting called 'Throw Exception on REST Error'. I must uncheck this box. When unchecked, CPI will not trigger an Exception Subprocess for 4xx or 5xx codes. Instead, it will pass the HTTP status code (in CamelHttpResponseCode) and the error response body to the next step in the pipeline. I can then use a Router step to check the status code and handle the error payload gracefully.

Advanced Patterns & Optimization

Scenario 23: You need to aggregate daily sales files arriving independently via SFTP over 24 hours, and send one combined file at midnight. How do you design this?

Solution: I would use the Aggregator step. The incoming messages would be read via a sender adapter. The Aggregator would be configured with a Correlation Expression (e.g., a constant or date string like 'Sales-yyyy-MM-dd') so all files that day group together. I would set the Aggregation Strategy (e.g., combine XML nodes). For the completion condition, I would use a Timeout (e.g., 24 hours) or a specific time-based trigger using a secondary completion IFlow with a Data Store.

Scenario 24: You have an IFlow that uses a Request-Reply to fetch a token, then another Request-Reply to call an API. The second call fails because standard Camel headers from the first call are interfering. How do you fix this?

Solution: This is a common issue where HTTP headers (like Authorization, CamelHttpUri, or CamelHttpResponseCode) from the first call persist and interfere with the second call. To resolve this, I would place a Content Modifier or a Filter step immediately after the first Request-Reply and explicitly delete all CamelHttp* headers and any other specific headers that are no longer needed before constructing the payload and headers for the second API call.

Scenario 25: You are migrating an SAP PI/PO UDF (User Defined Function) that connects to a database to perform a lookup inside a Message Mapping. How do you handle this in CPI?

Solution: Direct JDBC lookups inside Message Mappings (via Groovy UDFs) are highly discouraged in CPI due to performance and connection pool limitations. Instead, I would redesign the flow. I would extract the keys needed for lookup from the payload, use a Content Enricher with a JDBC adapter to fetch the lookup data from the database before the mapping step, and merge it with the source payload. Then, the Message Mapping can simply map the merged XML without executing any remote calls.

Scenario 26: You have a requirement to dynamically route a message to one of 50 different target URLs based on a company code. Using a Router with 50 branches is unmanageable. What is the better approach?

Solution: I would use Dynamic Routing. First, I would maintain a Value Mapping or a custom Groovy script/lookup table that maps the Company Code to a specific Target URL. In the IFlow, I would read the company code, perform the lookup, and store the resulting URL in an Exchange Property (e.g., Target_URL). In the HTTP receiver adapter, I would configure the Address field dynamically using ${property.Target_URL}, entirely eliminating the need for a Router step.

Scenario 27: The OData V2 adapter is fetching 100,000 records, which times out. How do you optimize this extraction?

Solution: I would implement pagination (chunking) using the OData adapter's built-in 'Process in Pages' feature. I would configure the 'Page Size' (e.g., 1000 or 5000 records per page). The adapter will then execute multiple backend calls sequentially, passing each chunk into the IFlow as a separate message. To prevent the IFlow from being overloaded, I can combine this with a ProcessDirect call to a sub-flow that processes each page asynchronously.

Scenario 28: A client requires CORS (Cross-Origin Resource Sharing) to be enabled on a CPI HTTPS endpoint so their web application can call it directly from a browser. How is this achieved?

Solution: CPI HTTPS endpoints do not support CORS preflight (OPTIONS) requests natively out-of-the-box. To handle this, I would expose the CPI IFlow through SAP API Management (APIM). In APIM, I would create an API Proxy pointing to the CPI endpoint and attach a standard CORS Policy to the proxy. The policy will handle the OPTIONS requests and inject the required Access-Control-Allow-Origin headers, keeping the CPI IFlow clean and secure.

Scenario 29: You need to zip multiple attachments from an incoming email and send them as a single .zip file to an SFTP server. How do you implement this?

Solution: I would use a Groovy script. I would read the message.getAttachments() collection. I would create a ByteArrayOutputStream and wrap it in a ZipOutputStream. I would iterate through the attachments, create a ZipEntry for each attachment using its filename, and write the attachment's payload (bytes) into the zip stream. Finally, I would close the stream and set the resulting byte array as the main message body, which is then routed to the SFTP adapter.

Scenario 30: You have an XSLT mapping, but you also need to set a Camel exchange property dynamically based on the XML content. Can you do this inside XSLT?

Solution: Yes, in CPI's XSLT mapping, you can interact with Camel exchange properties and headers by declaring the specific Camel namespace. You define xmlns:cpi="http://sap.com/it/" in the stylesheet. Then, you can use CPI-specific extension functions like or cpi:setHeader() directly within the XSLT logic, allowing dynamic variables based on the transformation logic.

No comments:

Post a Comment