GraphQL avec ABAP Cloud : Alternatives API à OData

Catégorie
Integration
Publié
Auteur
Johannes

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 :

ConceptDescription
QueryLire des données (comparable à GET)
MutationModifier des données (comparable à POST/PUT/DELETE)
SubscriptionMises à jour en temps réel via WebSocket
SchemaDéfinition d’API typée
ResolverLogique de données côté serveur

Exemple de requête GraphQL

# Client fragt exakt die benötigten Felder an
query 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 :

AspectGraphQLOData
OrigineFacebook/Meta (2015)Microsoft/SAP (2007)
Flexibilité des requêtesTrès élevée (le client détermine les champs)Moyenne ($select, $expand)
Ressources multiplesUne requête pour plusieurs entitésPlusieurs requêtes ou $expand
Over-/UnderfetchingMinimal (requêtes précises)Possible (entités fixes)
Système de typesFortement typé (Schema)Fortement typé (EDMX/CSDL)
CachingComplexe (requêtes POST)Simple (GET + cache HTTP)
VersionnageÉvolution du schémaVersionnage URI
Support SAPLimitéNatif (RAP, Gateway)
OutillageGraphiQL, ApolloFiori Elements, Gateway
Requêtes batchNatif (plusieurs requêtes)Point de terminaison $batch
Temps réelSubscriptionsPas de support natif

Avantages de GraphQL

  1. Pas d’over-fetching : Le client ne reçoit que les champs nécessaires
  2. Pas d’under-fetching : Une requête pour des données complexes et imbriquées
  3. Système de types fort : Le schéma comme contrat entre client et serveur
  4. Introspection : L’API est auto-documentée
  5. Support temps réel : Subscriptions pour les notifications push

Avantages d’OData (dans le contexte SAP)

  1. Intégration SAP native : RAP, Fiori Elements, Gateway
  2. Caching HTTP : Les requêtes GET sont cachables
  3. Outillage établi : Large support SAP
  4. Standardisé : Standard OASIS avec extensions SAP
  5. 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 :

OptionDescriptionIntégration ABAP
SAP GraphAPI unifiée pour les produits SAPConsomme les API SAP, pas de backend ABAP
Apollo FederationPasserelle GraphQL sur BTPABAP comme source de données via OData
Custom GraphQL ServiceImplé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 Definition
const 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 Mapping
const 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 $expand
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_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énarioJustification
Applications mobilesOptimisation de la bande passante par des requêtes précises
UI complexesBeaucoup de données imbriquées en une seule requête
Exigences temps réelSubscriptions pour les mises à jour en direct
Frontend non-SAPReact/Vue/Angular avec Apollo Client
Agrégation d’APIPlusieurs backends via une passerelle

Privilégier OData pour :

ScénarioJustification
SAP FioriIntégration native Fiori Elements
ABAP Cloud natifServices basés sur RAP sans middleware
Caching simpleRequêtes HTTP GET
Consommation standard SAPAPI 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).
" Fehlerbehandlung
ENDTRY.

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 :

  1. Exigences pilotées par le frontend : Lorsque les équipes React/Vue travaillent avec Apollo
  2. Agrégation d’API : Plusieurs backends via une passerelle unifiée
  3. Optimisation mobile : Applications sensibles à la bande passante
  4. 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 :