GraphQL s’est imposé comme une alternative API moderne à REST et OData. Mais qu’en est-il du support dans ABAP Cloud ? Cet article compare GraphQL avec OData, montre l’état actuel du support SAP et présente des solutions de contournement pratiques pour les scénarios GraphQL.
Qu’est-ce que GraphQL ?
GraphQL est un langage de requête pour les API développé par Facebook (Meta). Contrairement à REST et OData, c’est le client qui définit exactement les données dont il a besoin - pas le serveur.
Concepts clés de GraphQL :
| Concept | Description |
|---|---|
| Query | Lire des données (comparable à GET) |
| Mutation | Modifier des données (comparable à POST/PUT/DELETE) |
| Subscription | Mises à jour en temps réel via WebSocket |
| Schema | Définition d’API typée |
| Resolver | Logique de données côté serveur |
Exemple de requête GraphQL
# Client fragt exakt die benötigten Felder anquery GetOrder { order(id: "4711") { orderId customer { name email } items { product { name price } quantity } totalAmount }}Réponse : Seuls les champs demandés sont retournés - pas de données superflues.
Comparaison : GraphQL vs OData
Les deux protocoles répondent à des exigences similaires, mais ont des forces différentes :
| Aspect | GraphQL | OData |
|---|---|---|
| Origine | Facebook/Meta (2015) | Microsoft/SAP (2007) |
| Flexibilité des requêtes | Très élevée (le client détermine les champs) | Moyenne ($select, $expand) |
| Ressources multiples | Une requête pour plusieurs entités | Plusieurs requêtes ou $expand |
| Over-/Underfetching | Minimal (requêtes précises) | Possible (entités fixes) |
| Système de types | Fortement typé (Schema) | Fortement typé (EDMX/CSDL) |
| Caching | Complexe (requêtes POST) | Simple (GET + cache HTTP) |
| Versionnage | Évolution du schéma | Versionnage URI |
| Support SAP | Limité | Natif (RAP, Gateway) |
| Outillage | GraphiQL, Apollo | Fiori Elements, Gateway |
| Requêtes batch | Natif (plusieurs requêtes) | Point de terminaison $batch |
| Temps réel | Subscriptions | Pas de support natif |
Avantages de GraphQL
- Pas d’over-fetching : Le client ne reçoit que les champs nécessaires
- Pas d’under-fetching : Une requête pour des données complexes et imbriquées
- Système de types fort : Le schéma comme contrat entre client et serveur
- Introspection : L’API est auto-documentée
- Support temps réel : Subscriptions pour les notifications push
Avantages d’OData (dans le contexte SAP)
- Intégration SAP native : RAP, Fiori Elements, Gateway
- Caching HTTP : Les requêtes GET sont cachables
- Outillage établi : Large support SAP
- Standardisé : Standard OASIS avec extensions SAP
- Support batch : $batch pour les transactions
État actuel : GraphQL dans SAP/ABAP Cloud (2026)
En février 2026, il n’y a pas de support natif GraphQL dans ABAP Cloud. La technologie API stratégique de SAP reste OData en combinaison avec le modèle de programmation d’application RESTful ABAP (RAP).
Options GraphQL SAP BTP
Sur la plateforme SAP Business Technology Platform, les possibilités suivantes existent :
| Option | Description | Intégration ABAP |
|---|---|---|
| SAP Graph | API unifiée pour les produits SAP | Consomme les API SAP, pas de backend ABAP |
| Apollo Federation | Passerelle GraphQL sur BTP | ABAP comme source de données via OData |
| Custom GraphQL Service | Implémentation personnalisée (Node.js/Java) | Appelle les API ABAP Cloud |
SAP Graph (Beta)
SAP Graph est l’approche de SAP pour une couche API unifiée qui regroupe différents produits SAP. Il utilise des concepts similaires à GraphQL, mais est principalement destiné à la consommation de données SAP - pas à la création de points de terminaison GraphQL personnalisés dans ABAP.
Solution de contournement 1 : Passerelle GraphQL sur BTP
L’architecture recommandée est une passerelle GraphQL sur la SAP BTP, qui utilise les services OData d’ABAP Cloud comme backend.
┌─────────────────────────────────────────────────────────┐│ Client (Web/Mobile) ││ │ ││ GraphQL Query ││ ▼ ││ ┌─────────────────────────────────────────────────┐ ││ │ GraphQL Gateway (BTP) │ ││ │ Node.js + Apollo Server │ ││ └─────────────────────────────────────────────────┘ ││ │ ││ OData Requests ││ ▼ ││ ┌─────────────────────────────────────────────────┐ ││ │ ABAP Cloud (RAP Services) │ ││ │ OData V4 Endpoints │ ││ └─────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────┘Apollo Server comme passerelle GraphQL
// 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; } }};Service RAP ABAP Cloud (Backend)
Le backend ABAP Cloud continue de fournir des services OData :
-- 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;}Solution de contournement 2 : Point de terminaison HTTP personnalisé dans ABAP
Pour des scénarios de type GraphQL simples, un gestionnaire HTTP personnalisé peut être implémenté dans ABAP Cloud. Ceci n’est pas recommandé pour les scénarios de production, mais montre la faisabilité.
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.Limitations :
- Pas de vrai parsing GraphQL
- Pas de support de subscription
- Pas d’outillage standard (GraphiQL)
- Effort de maintenance
Comparaison de code : GraphQL vs OData
Scénario : Charger une commande avec client et articles
GraphQL (une requête) :
query GetOrderWithDetails { order(id: "4711") { orderId totalAmount customer { name email } items { quantity product { name price } } }}OData (avec $expand) :
GET /Orders('4711')?$select=OrderId,TotalAmount &$expand=Customer($select=Name,Email), Items($select=Quantity;$expand=Product($select=Name,Price))ABAP Cloud HTTP Client pour 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 ).Quand GraphQL, quand OData ?
Privilégier GraphQL pour :
| Scénario | Justification |
|---|---|
| Applications mobiles | Optimisation de la bande passante par des requêtes précises |
| UI complexes | Beaucoup de données imbriquées en une seule requête |
| Exigences temps réel | Subscriptions pour les mises à jour en direct |
| Frontend non-SAP | React/Vue/Angular avec Apollo Client |
| Agrégation d’API | Plusieurs backends via une passerelle |
Privilégier OData pour :
| Scénario | Justification |
|---|---|
| SAP Fiori | Intégration native Fiori Elements |
| ABAP Cloud natif | Services basés sur RAP sans middleware |
| Caching simple | Requêtes HTTP GET |
| Consommation standard SAP | API S/4HANA, services BTP |
| Opérations batch | $batch pour les transactions |
Intégration : Client GraphQL dans ABAP Cloud
Si un système externe propose GraphQL, ABAP Cloud peut agir comme client GraphQL :
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.Utilisation :
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.Conclusion et recommandation
GraphQL n’est pas disponible nativement dans ABAP Cloud - et ce n’est pas non plus la direction stratégique de SAP. OData reste la technologie API principale pour les systèmes SAP.
Néanmoins, il existe des scénarios GraphQL valides :
- Exigences pilotées par le frontend : Lorsque les équipes React/Vue travaillent avec Apollo
- Agrégation d’API : Plusieurs backends via une passerelle unifiée
- Optimisation mobile : Applications sensibles à la bande passante
- Intégration non-SAP : Lorsque des systèmes tiers nécessitent GraphQL
Architecture recommandée :
- ABAP Cloud fournit des services OData (RAP)
- Passerelle GraphQL sur BTP (Node.js/Apollo) transforme les requêtes
- Les clients communiquent via GraphQL avec la passerelle
Cette architecture combine les forces des deux mondes : l’intégration OData éprouvée de SAP dans le backend et la flexibilité de GraphQL pour les frontends modernes.
Articles complémentaires :
- OData Services in ABAP Cloud
- HTTP Client pour API externes
- RAP External API Consumption
- SAP CAP vs ABAP Cloud