GraphQL hat sich als moderne API-Alternative zu REST und OData etabliert. Aber wie sieht es mit der Unterstützung in ABAP Cloud aus? Dieser Artikel vergleicht GraphQL mit OData, zeigt den aktuellen Stand der SAP-Unterstützung und präsentiert praktische Workarounds für GraphQL-Szenarien.
Was ist GraphQL?
GraphQL ist eine von Facebook (Meta) entwickelte Query-Sprache für APIs. Im Gegensatz zu REST und OData definiert der Client exakt, welche Daten er benötigt – nicht der Server.
Kernkonzepte von GraphQL:
| Konzept | Beschreibung |
|---|---|
| Query | Daten lesen (vergleichbar mit GET) |
| Mutation | Daten ändern (vergleichbar mit POST/PUT/DELETE) |
| Subscription | Echtzeit-Updates via WebSocket |
| Schema | Typisierte API-Definition |
| Resolver | Serverseitige Daten-Logik |
GraphQL Query-Beispiel
# Client fragt exakt die benötigten Felder anquery GetOrder { order(id: "4711") { orderId customer { name email } items { product { name price } quantity } totalAmount }}Antwort: Nur die angefragten Felder werden zurückgegeben – keine überflüssigen Daten.
Vergleich: GraphQL vs OData
Beide Protokolle adressieren ähnliche Anforderungen, haben aber unterschiedliche Stärken:
| Aspekt | GraphQL | OData |
|---|---|---|
| Herkunft | Facebook/Meta (2015) | Microsoft/SAP (2007) |
| Query-Flexibilität | Sehr hoch (Client bestimmt Felder) | Mittel ($select, $expand) |
| Mehrere Ressourcen | Eine Query für mehrere Entitäten | Mehrere Requests oder $expand |
| Over-/Underfetching | Minimal (präzise Abfragen) | Möglich (feste Entitäten) |
| Typsystem | Stark typisiert (Schema) | Stark typisiert (EDMX/CSDL) |
| Caching | Komplex (POST-Requests) | Einfach (GET + HTTP-Caching) |
| Versionierung | Schema-Evolution | URI-Versionierung |
| SAP-Support | Begrenzt | Nativ (RAP, Gateway) |
| Tooling | GraphiQL, Apollo | Fiori Elements, Gateway |
| Batch-Requests | Nativ (mehrere Queries) | $batch-Endpoint |
| Echtzeit | Subscriptions | Keine native Unterstützung |
Vorteile von GraphQL
- Keine Over-Fetching: Client erhält nur benötigte Felder
- Keine Under-Fetching: Eine Query für komplexe, verschachtelte Daten
- Starkes Typsystem: Schema als Vertrag zwischen Client und Server
- Introspection: API ist selbstdokumentierend
- Echtzeit-Support: Subscriptions für Push-Benachrichtigungen
Vorteile von OData (im SAP-Kontext)
- Native SAP-Integration: RAP, Fiori Elements, Gateway
- HTTP-Caching: GET-Requests sind cachebar
- Etabliertes Tooling: Breite SAP-Unterstützung
- Standardisiert: OASIS-Standard mit SAP-Erweiterungen
- Batch-Support: $batch für Transaktionen
Aktueller Stand: GraphQL in SAP/ABAP Cloud (2026)
Stand Februar 2026 gibt es keine native GraphQL-Unterstützung in ABAP Cloud. SAPs strategische API-Technologie bleibt OData in Kombination mit dem ABAP RESTful Application Programming Model (RAP).
SAP BTP GraphQL-Optionen
Auf der SAP Business Technology Platform gibt es folgende Möglichkeiten:
| Option | Beschreibung | ABAP-Integration |
|---|---|---|
| SAP Graph | Unified API für SAP-Produkte | Konsumiert SAP-APIs, kein ABAP-Backend |
| Apollo Federation | GraphQL Gateway auf BTP | ABAP als Datenquelle via OData |
| Custom GraphQL Service | Eigene Implementierung (Node.js/Java) | Ruft ABAP Cloud APIs auf |
SAP Graph (Beta)
SAP Graph ist SAPs Ansatz für eine einheitliche API-Schicht, die verschiedene SAP-Produkte zusammenführt. Es verwendet GraphQL-ähnliche Konzepte, ist aber primär für die Konsumierung von SAP-Daten gedacht – nicht für die Erstellung eigener GraphQL-Endpunkte in ABAP.
Workaround 1: GraphQL-Gateway auf BTP
Die empfohlene Architektur ist ein GraphQL-Gateway auf der SAP BTP, das ABAP Cloud OData-Services als Backend nutzt.
┌─────────────────────────────────────────────────────────┐│ Client (Web/Mobile) ││ │ ││ GraphQL Query ││ ▼ ││ ┌─────────────────────────────────────────────────┐ ││ │ GraphQL Gateway (BTP) │ ││ │ Node.js + Apollo Server │ ││ └─────────────────────────────────────────────────┘ ││ │ ││ OData Requests ││ ▼ ││ ┌─────────────────────────────────────────────────┐ ││ │ ABAP Cloud (RAP Services) │ ││ │ OData V4 Endpoints │ ││ └─────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────┘Apollo Server als GraphQL-Gateway
// srv/graphql-gateway.js (CAP/Node.js auf BTP)const { ApolloServer, gql } = require('apollo-server-express');const axios = require('axios');
// GraphQL Schema Definitionconst typeDefs = gql` type Order { orderId: ID! customerId: String customer: Customer totalAmount: Float currency: String items: [OrderItem] }
type Customer { customerId: ID! name: String email: String }
type OrderItem { itemId: ID! productId: String quantity: Int product: Product }
type Product { productId: ID! name: String price: Float }
type Query { order(id: ID!): Order orders(top: Int, skip: Int): [Order] customer(id: ID!): Customer }`;
// Resolver: GraphQL -> OData Mappingconst resolvers = { Query: { order: async (_, { id }, { dataSources }) => { // OData-Request an ABAP Cloud const response = await dataSources.abapAPI.get( `/sap/opu/odata4/sap/zorderservice/Orders('${id}')` ); return response.data; }, orders: async (_, { top = 10, skip = 0 }, { dataSources }) => { const response = await dataSources.abapAPI.get( `/sap/opu/odata4/sap/zorderservice/Orders?$top=${top}&$skip=${skip}` ); return response.data.value; } }, Order: { // Resolver für verschachtelte Daten customer: async (order, _, { dataSources }) => { const response = await dataSources.abapAPI.get( `/sap/opu/odata4/sap/zorderservice/Customers('${order.customerId}')` ); return response.data; }, items: async (order, _, { dataSources }) => { const response = await dataSources.abapAPI.get( `/sap/opu/odata4/sap/zorderservice/Orders('${order.orderId}')/Items` ); return response.data.value; } }};ABAP Cloud RAP Service (Backend)
Das ABAP Cloud Backend stellt weiterhin OData-Services bereit:
-- CDS View Entity für Orders@AccessControl.authorizationCheck: #CHECK@EndUserText.label: 'Order'define view entity Z_I_Order as select from zorder association [1..1] to Z_I_Customer as _Customer on $projection.CustomerId = _Customer.CustomerId association [0..*] to Z_I_OrderItem as _Items on $projection.OrderId = _Items.OrderId{ key order_id as OrderId, customer_id as CustomerId, total_amount as TotalAmount, currency as Currency,
_Customer, _Items}-- Service Definition@EndUserText.label: 'Order Service'define service Z_SD_Order { expose Z_C_Order as Orders; expose Z_C_Customer as Customers; expose Z_C_OrderItem as OrderItems;}Workaround 2: Custom HTTP Endpoint in ABAP
Für einfache GraphQL-ähnliche Szenarien kann ein Custom HTTP Handler in ABAP Cloud implementiert werden. Dies ist nicht empfohlen für produktive Szenarien, zeigt aber die Machbarkeit.
CLASS zcl_graphql_handler DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_http_service_extension.
PRIVATE SECTION. METHODS parse_query IMPORTING iv_query TYPE string EXPORTING ev_entity TYPE string et_fields TYPE string_table.
METHODS execute_query IMPORTING iv_entity TYPE string it_fields TYPE string_table RETURNING VALUE(rv_json) TYPE string.ENDCLASS.
CLASS zcl_graphql_handler IMPLEMENTATION.
METHOD if_http_service_extension~handle_request. DATA: lv_body TYPE string, lv_entity TYPE string, lt_fields TYPE string_table, lv_result TYPE string.
" Request Body lesen (vereinfachtes GraphQL-Parsing) lv_body = request->get_text( ).
" Query parsen (stark vereinfacht) parse_query( EXPORTING iv_query = lv_body IMPORTING ev_entity = lv_entity et_fields = lt_fields ).
" Daten abfragen lv_result = execute_query( iv_entity = lv_entity it_fields = lt_fields ).
" Response response->set_text( lv_result ). response->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ). ENDMETHOD.
METHOD parse_query. " Vereinfachtes Parsing - produktiv würde ein Parser benötigt " Beispiel: { orders { orderId totalAmount } } " ... ENDMETHOD.
METHOD execute_query. " Dynamische Feldauswahl basierend auf GraphQL-Query " In der Praxis: CDS View mit dynamischer Projektion " ... ENDMETHOD.
ENDCLASS.Einschränkungen:
- Kein echtes GraphQL-Parsing
- Keine Subscription-Unterstützung
- Kein Standard-Tooling (GraphiQL)
- Wartungsaufwand
Code-Vergleich: GraphQL vs OData
Szenario: Bestellung mit Kunde und Artikeln laden
GraphQL (eine Query):
query GetOrderWithDetails { order(id: "4711") { orderId totalAmount customer { name email } items { quantity product { name price } } }}OData (mit $expand):
GET /Orders('4711')?$select=OrderId,TotalAmount &$expand=Customer($select=Name,Email), Items($select=Quantity;$expand=Product($select=Name,Price))ABAP Cloud HTTP Client für OData:
" OData-Request mit $expandDATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_OUTBOUND_ODATA' service_id = 'Z_ODATA_SERVICE' ) ).
DATA(lo_request) = lo_client->get_http_request( ).lo_request->set_uri_path( '/sap/opu/odata4/sap/zorderservice/Orders(''4711'')' && '?$expand=Customer,Items($expand=Product)' ).
DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>get ).DATA(lv_json) = lo_response->get_text( ).
" JSON parsen/ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = ls_order ).Wann GraphQL, wann OData?
GraphQL bevorzugen bei:
| Szenario | Begründung |
|---|---|
| Mobile Apps | Bandbreiten-Optimierung durch präzise Queries |
| Komplexe UIs | Viele verschachtelte Daten in einem Request |
| Echtzeit-Anforderungen | Subscriptions für Live-Updates |
| Nicht-SAP Frontend | React/Vue/Angular mit Apollo Client |
| API-Aggregation | Mehrere Backends über ein Gateway |
OData bevorzugen bei:
| Szenario | Begründung |
|---|---|
| SAP Fiori | Native Fiori Elements-Integration |
| ABAP Cloud native | RAP-basierte Services ohne Middleware |
| Einfaches Caching | HTTP GET-Requests |
| SAP-Standard-Konsumption | S/4HANA APIs, BTP Services |
| Batch-Operationen | $batch für Transaktionen |
Integration: GraphQL-Client in ABAP Cloud
Wenn ein externes System GraphQL anbietet, kann ABAP Cloud als GraphQL-Client fungieren:
CLASS zcl_graphql_client DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. METHODS execute_query IMPORTING iv_query TYPE string iv_variables TYPE string OPTIONAL RETURNING VALUE(rv_response) TYPE string RAISING cx_web_http_client_error.ENDCLASS.
CLASS zcl_graphql_client IMPLEMENTATION.
METHOD execute_query. " GraphQL-Request bauen DATA(lv_body) = |\{"query": "{ iv_query }"|. IF iv_variables IS NOT INITIAL. lv_body = lv_body && |, "variables": { iv_variables }|. ENDIF. lv_body = lv_body && |\}|.
" HTTP Client erstellen DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_GRAPHQL_OUTBOUND' service_id = 'GRAPHQL_API' ) ).
DATA(lo_request) = lo_client->get_http_request( ). lo_request->set_uri_path( '/graphql' ). lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ). lo_request->set_text( lv_body ).
" POST-Request ausführen DATA(lo_response) = lo_client->execute( i_method = if_web_http_client=>post ). rv_response = lo_response->get_text( ).
lo_client->close( ). ENDMETHOD.
ENDCLASS.Verwendung:
DATA(lo_gql) = NEW zcl_graphql_client( ).
DATA(lv_query) = |query \{ user(id: "123") \{ name email \} \}|.
TRY. DATA(lv_result) = lo_gql->execute_query( lv_query ). " JSON-Response verarbeiten... CATCH cx_web_http_client_error INTO DATA(lx_error). " FehlerbehandlungENDTRY.Fazit und Empfehlung
GraphQL ist nicht nativ in ABAP Cloud verfügbar – und das ist auch nicht SAPs strategische Richtung. OData bleibt die primäre API-Technologie für SAP-Systeme.
Dennoch gibt es valide GraphQL-Szenarien:
- Frontend-getriebene Anforderungen: Wenn React/Vue-Teams mit Apollo arbeiten
- API-Aggregation: Mehrere Backends über ein einheitliches Gateway
- Mobile Optimierung: Bandbreiten-sensitive Anwendungen
- Nicht-SAP Integration: Wenn Drittsysteme GraphQL erfordern
Empfohlene Architektur:
- ABAP Cloud stellt OData-Services bereit (RAP)
- GraphQL-Gateway auf BTP (Node.js/Apollo) transformiert Queries
- Clients kommunizieren über GraphQL mit dem Gateway
Diese Architektur kombiniert die Stärken beider Welten: SAPs bewährte OData-Integration im Backend und GraphQLs Flexibilität für moderne Frontends.
Weiterführende Artikel:
- OData Services in ABAP Cloud
- HTTP Client für externe APIs
- RAP External API Consumption
- SAP CAP vs ABAP Cloud