| name | sap-integration-suite-advanced |
| description | Advanced SAP Integration Suite skill. Use when writing Groovy scripts for iFlows, configuring API Management policies, deploying Edge Integration Cell, or building B2B/EDI integrations. If the user mentions CPI Groovy script, API policy, Edge Cell, TPM, or advanced iFlow mapping, use this skill.
|
| license | MIT |
| metadata | {"author":"SAP Skills Community","version":"1.0.0","last_verified":"2026-03-24"} |
Advanced SAP Integration Suite — Groovy, API Mgmt & Edge
Related Skills
sap-event-mesh — Event-driven integration patterns
sap-s4hana-extensibility — S/4HANA API consumption via Integration Suite
sap-security-authorization — OAuth/SAML policies in API Management
sap-devops-cicd — Integration content transport and CI/CD
Quick Start
Advanced capabilities:
| Capability | Use Case | Key Feature |
|---|
| Cloud Integration | A2A, B2B, cloud-to-on-prem | iFlows, Groovy, mapping |
| API Management | API facade, rate limiting, analytics | Policies, Developer Portal |
| Integration Advisor | B2B message mapping | MAG (Message Application Group) |
| Trading Partner Management | EDI/B2B partner onboarding | AS2, EDIFACT, X12 |
| Edge Integration Cell | On-premise/private cloud runtime | Kubernetes-based, hybrid |
| Open Connectors | 170+ SaaS connectors | Pre-built adapters |
Core Concepts
iFlow Processing Pipeline
Sender ──► Sender Adapter ──► Integration Flow ──► Receiver Adapter ──► Receiver
│
┌───────────────┼───────────────┐
▼ ▼ ▼
Content Message Router /
Modifier Mapping Splitter
│ │ │
▼ ▼ ▼
Groovy XSLT / Aggregator
Script Graphical
API Management Policy Types
| Category | Policy | Purpose |
|---|
| Traffic | Spike Arrest | Prevent traffic spikes |
| Traffic | Quota | Limit calls per time period |
| Traffic | Concurrent Rate Limit | Max simultaneous connections |
| Security | OAuth v2.0 | Token validation |
| Security | SAML Assertion | SAML token validation |
| Security | Verify API Key | Simple API key auth |
| Mediation | JSON to XML | Format conversion |
| Mediation | Assign Message | Set headers/variables |
| Extension | JavaScript | Custom policy logic |
Edge Integration Cell Architecture
┌─────────────────────────────────────────┐
│ Customer Data Center / Private Cloud │
│ ┌───────────────────────────────────┐ │
│ │ Edge Integration Cell │ │
│ │ ┌─────────┐ ┌──────────────┐ │ │
│ │ │ Runtime │ │ Edge Event │ │ │
│ │ │ (iFlows) │ │ Broker │ │ │
│ │ └────┬─────┘ └──────┬───────┘ │ │
│ │ │ │ │ │
│ │ ┌────┴───────────────┴────┐ │ │
│ │ │ Kubernetes (K3s/K8s) │ │ │
│ │ └─────────────────────────┘ │ │
│ └───────────────┬───────────────────┘ │
│ │ HTTPS (outbound only) │
└──────────────────┼──────────────────────┘
▼
SAP Integration Suite
(Cloud Control Plane)
Common Patterns
Pattern 1: Groovy Script — JSON Transformation
import com.sap.gateway.ip.core.customdev.util.Message
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def Message processData(Message message) {
def body = message.getBody(String)
def json = new JsonSlurper().parseText(body)
// Transform structure
def result = json.orders.collect { order ->
[
orderNumber: order.id,
customerName: order.customer?.name ?: 'Unknown',
totalAmount: order.items?.sum { it.price * it.quantity } ?: 0,
currency: order.currency ?: 'EUR',
lineItems: order.items?.collect { item ->
[
materialId: item.productId,
description: item.description?.take(40),
quantity: item.quantity,
unitPrice: item.price
]
} ?: []
]
}
message.setBody(JsonOutput.toJson([salesOrders: result]))
message.setHeader('Content-Type', 'application/json')
message.setProperty('OrderCount', result.size())
return message
}
Pattern 2: Groovy Script — Error Handling & Logging
import com.sap.gateway.ip.core.customdev.util.Message
import org.apache.camel.Exchange
def Message processData(Message message) {
def log = messageLogFactory.getMessageLog(message)
def props = message.getProperties()
try {
def body = message.getBody(String)
// Validate input
if (!body || body.trim().isEmpty()) {
throw new IllegalArgumentException("Empty message body")
}
// Log for monitoring (appears in Message Processing Log)
log?.addAttachmentAsString('InputPayload', body, 'application/json')
// Process...
def result = transform(body)
log?.setStringProperty('ProcessingStatus', 'SUCCESS')
log?.setStringProperty('RecordCount', result.size().toString())
message.setBody(result)
} catch (Exception e) {
// Set error details for exception subprocess
message.setProperty('ErrorMessage', e.message)
message.setProperty('ErrorClass', e.class.simpleName)
message.setProperty('ErrorTimestamp', new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'"))
log?.setStringProperty('ProcessingStatus', 'ERROR')
log?.setStringProperty('ErrorDetail', e.message)
// Re-throw to trigger error handling
throw e
}
return message
}
Pattern 3: Groovy Script — Dynamic Routing
import com.sap.gateway.ip.core.customdev.util.Message
def Message processData(Message message) {
def body = new groovy.json.JsonSlurper().parseText(message.getBody(String))
// Determine route based on payload
def routeTarget = switch(body.documentType) {
case 'INVOICE' -> 'InvoiceEndpoint'
case 'CREDIT_MEMO' -> 'CreditMemoEndpoint'
case 'PO' -> 'PurchaseOrderEndpoint'
default -> 'DefaultEndpoint'
}
// Set routing header for Router step
message.setHeader('RouteTarget', routeTarget)
// Set dynamic endpoint URL
def endpoints = [
'InvoiceEndpoint': 'https://erp.example.com/api/invoices',
'CreditMemoEndpoint': 'https://erp.example.com/api/credit-memos',
'PurchaseOrderEndpoint': 'https://erp.example.com/api/purchase-orders',
'DefaultEndpoint': 'https://erp.example.com/api/documents'
]
message.setProperty('DynamicEndpointURL', endpoints[routeTarget])
return message
}
Pattern 4: API Management — Rate Limiting Policy
<SpikeArrest async="false" continueOnError="false" enabled="true"
xmlns="http://www.sap.com/apimgmt">
<DisplayName>Spike Arrest - 30ps</DisplayName>
<Rate>30ps</Rate>
<Identifier ref="request.header.X-Client-ID"/>
</SpikeArrest>
<Quota async="false" continueOnError="false" enabled="true" type="calendar"
xmlns="http://www.sap.com/apimgmt">
<DisplayName>Monthly Quota</DisplayName>
<Allow count="10000"/>
<Interval>1</Interval>
<TimeUnit>month</TimeUnit>
<StartTime>2026-01-01 00:00:00</StartTime>
<Identifier ref="request.header.apiKey"/>
<Distributed>true</Distributed>
</Quota>
<OAuthV2 async="false" continueOnError="false" enabled="true"
xmlns="http://www.sap.com/apimgmt">
<DisplayName>Verify OAuth Token</DisplayName>
<Operation>VerifyAccessToken</Operation>
<AccessToken>request.header.Authorization</AccessToken>
<Scope>read write</Scope>
</OAuthV2>
<ResponseCache async="false" continueOnError="false" enabled="true"
xmlns="http://www.sap.com/apimgmt">
<DisplayName>Cache GET responses</DisplayName>
<CacheKey>
<KeyFragment ref="request.uri"/>
<KeyFragment ref="request.header.Accept"/>
</CacheKey>
<ExpirySettings>
<TimeoutInSec>300</TimeoutInSec>
</ExpirySettings>
<SkipCacheLookup>request.verb != "GET"</SkipCacheLookup>
</ResponseCache>
Pattern 5: XSLT Mapping — IDoc to JSON
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:idoc="urn:sap-com:document:sap:idoc:messages">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:text>{"orders":[</xsl:text>
<xsl:for-each select="//ORDERS05/IDOC">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:text>{"orderNumber":"</xsl:text>
<xsl:value-of select="E1EDK01/BELNR"/>
<xsl:text>","orderDate":"</xsl:text>
<xsl:value-of select="concat(
substring(E1EDK01/DATUM,1,4),'-',
substring(E1EDK01/DATUM,5,2),'-',
substring(E1EDK01/DATUM,7,2))"/>
<xsl:text>","items":[</xsl:text>
<xsl:for-each select="E1EDP01">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:text>{"lineItem":"</xsl:text>
<xsl:value-of select="POSEX"/>
<xsl:text>","material":"</xsl:text>
<xsl:value-of select="normalize-space(MATNR)"/>
<xsl:text>","quantity":</xsl:text>
<xsl:value-of select="MENGE"/>
<xsl:text>}</xsl:text>
</xsl:for-each>
<xsl:text>]}</xsl:text>
</xsl:for-each>
<xsl:text>]}</xsl:text>
</xsl:template>
</xsl:stylesheet>
Pattern 6: B2B Integration — AS2 with TPM
Trading Partner Setup:
┌──────────────┐ AS2/HTTPS ┌──────────────────┐
│ Partner A │───────────────►│ Integration Suite │
│ (Supplier) │ EDIFACT msg │ ┌──────────────┐ │
│ │◄───────────────│ │ TPM Config │ │
└──────────────┘ AS2 MDN │ │ - Partner ID │ │
│ │ - AS2 ID │ │
│ │ - Certificate│ │
│ │ - Agreement │ │
│ └──────┬───────┘ │
│ ▼ │
│ ┌──────────────┐ │
│ │ iFlow │ │
│ │ (EDI→XML→ │ │
│ │ IDoc/OData) │ │
│ └──────┬───────┘ │
└─────────┼─────────┘
▼
SAP S/4HANA
TPM Configuration checklist:
- Create Trading Partner profile (AS2 ID, certificates)
- Define Agreement (message type: ORDERS, INVOIC, DESADV)
- Configure B2B adapter in iFlow (AS2 sender/receiver)
- Map EDI segments to SAP IDoc/API structure
- Set up MDN (Message Disposition Notification) for acknowledgment
- Test with partner's test environment before go-live
Error Catalog
| Error | Context | Root Cause | Fix |
|---|
Groovy: NullPointerException | Script step | Accessing null property | Add null-safe operator ?. and default values |
Groovy: ClassNotFoundException | Custom library | JAR not uploaded to tenant | Upload via Integration Content → Resources |
HTTP 429 | API Management | Rate limit/quota exceeded | Adjust policy; contact API provider |
MPL: FAILED | Message Processing Log | iFlow step error | Check MPL attachments and trace for root cause |
Certificate expired | Receiver adapter | SSL/TLS cert expiration | Rotate certificate in Security Material |
AS2: MDN negative | B2B | Partner rejected message | Check EDI validation; verify message structure |
Mapping error | Message Mapping | Source/target mismatch | Compare source XML structure with mapping definition |
Edge: Pod CrashLoopBackOff | Edge Integration Cell | Memory/config issue | Check pod logs; increase resource limits |
Credential not found | Adapter auth | Missing Security Material | Deploy OAuth/Basic auth credentials to tenant |
Queue full | JMS adapter | Consumer too slow | Scale consumer iFlow; increase queue depth |
Performance Tips
- Groovy: Reuse parsers — Compile JsonSlurper once, reuse across messages; avoid
new in hot paths
- Streaming for large payloads — Use Groovy
XMLStreamReader instead of DOM for >10 MB XML
- Content Modifier over Script — Use Content Modifier for simple header/property changes; Groovy adds overhead
- JMS queues for decoupling — Use JMS between sender and receiver iFlows for retry and buffering
- API caching — Enable ResponseCache policy for read-heavy APIs; 5-min cache reduces backend calls 80%+
- Parallel processing — Use Splitter (parallel) + Aggregator for batch processing
- Edge Cell for latency — Deploy latency-sensitive iFlows to Edge; keep cloud for management only
- Minimize trace logging — Trace-level logging in production impacts throughput; use only for debugging
Gotchas
- Groovy sandbox: Integration Suite Groovy runs in a restricted sandbox — no file I/O, no network calls (use adapters)
- Groovy version: Integration Suite uses Groovy 2.4.x (not 4.x); avoid newer syntax
- iFlow versioning: Each deploy creates a new version; rollback by redeploying older version
- Edge Cell updates: Edge runtime must be kept within 2 versions of cloud; auto-update recommended
- API proxy vs. iFlow: API Management proxies are for facade/security; iFlows for transformation/routing
- JMS queue limits: Default 30 queues per tenant; each 9.3 GB max; request increase via support ticket
- B2B certificates: Partner certificates expire; set calendar reminders for rotation