Les APIs REST externes sont un element central des applications cloud modernes. Dans ABAP Cloud et RAP, il existe des methodes standardisees pour connecter des services externes de maniere securisee et robuste. Cet article presente le workflow complet de la configuration a l’implementation.
Apercu : Integration d’API dans RAP
| Aspect | Description |
|---|---|
| HTTP Client | CL_WEB_HTTP_CLIENT_MANAGER pour les appels cloud-native |
| Configuration | Communication Arrangements pour des credentials securises |
| JSON | /UI2/CL_JSON ou XCO pour la serialisation |
| Integration RAP | Custom Entities ou Determinations/Actions |
| Gestion des erreurs | Logique de retry, timeouts, gestion des exceptions |
Prerequis
Avant de pouvoir consommer des APIs externes dans ABAP Cloud, vous avez besoin de :
- Communication Scenario - Definit le type de communication
- Communication System - Decrit le systeme cible
- Communication Arrangement - Relie le Scenario au System
┌────────────────────────────────────────────────────────────┐│ Systeme ABAP Cloud ││ ││ ┌──────────────────┐ ┌─────────────────────────────┐ ││ │ Communication │ │ Communication Arrangement │ ││ │ Scenario │───>│ │ ││ │ Z_WEATHER_API │ │ Scenario: Z_WEATHER_API │ ││ └──────────────────┘ │ System: WEATHER_SERVICE │ ││ │ Service: /weather │ ││ ┌──────────────────┐ │ │ ││ │ Communication │───>│ Auth: OAuth2 / API-Key │ ││ │ System │ └─────────────────────────────┘ ││ │ WEATHER_SERVICE │ │ ││ │ api.weather.com │ │ ││ └──────────────────┘ ▼ ││ ┌─────────────────────────────┐ ││ │ HTTP Destination │ ││ │ cl_http_destination_provider│ ││ └─────────────────────────────┘ │└────────────────────────────────────────────────────────────┘Creer un Communication Scenario
1. Definition du service sortant
" Outbound Service: Z_WEATHER_OUTBOUND" Service ID: Z_WEATHER_OS_REST" Service Type: HTTP
@EndUserText.label: 'Weather API Outbound Service"define outbound service Z_WEATHER_OS_REST { service binding Z_WEATHER_SB;}2. Communication Scenario
Le Communication Scenario est cree dans ADT sous Other ABAP Repository Objects → Communication Management → Communication Scenario :
<?xml version="1.0" encoding="utf-8"?><scn:scenario xmlns:scn="http://sap.com/xi/BASIS/Communication" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" scn:id="Z_WEATHER_API" scn:version="1"> <scn:label>Weather API Integration</scn:label> <scn:description>Scenario pour connexion Weather API</scn:description> <scn:allowedInstances>MULTIPLE</scn:allowedInstances> <scn:communicationType>OUTBOUND</scn:communicationType> <scn:outboundServices> <scn:service scn:id="Z_WEATHER_OS_REST" scn:authMethod="BASIC_OR_OAUTH"/> </scn:outboundServices></scn:scenario>3. Configurer le Communication Arrangement
Dans le Fiori Launchpad sous Communication Arrangements :
| Champ | Valeur |
|---|---|
| Scenario | Z_WEATHER_API |
| Arrangement Name | Z_WEATHER_PROD |
| Communication System | WEATHER_API_SYSTEM |
| Service Path | /api/v1 |
| Authentication | OAuth 2.0 Client Credentials |
HTTP Client dans ABAP Cloud
Appel API de base
CLASS zcl_weather_api DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. TYPES: BEGIN OF ty_weather_response, location TYPE string, temperature TYPE decfloat16, humidity TYPE i, condition TYPE string, wind_speed TYPE decfloat16, updated_at TYPE timestamp, END OF ty_weather_response.
METHODS get_current_weather IMPORTING iv_city TYPE string RETURNING VALUE(rs_result) TYPE ty_weather_response RAISING cx_http_dest_provider_error cx_web_http_client_error.
PRIVATE SECTION. CONSTANTS: c_comm_scenario TYPE if_com_scenario_factory=>ty_cscn_id VALUE 'Z_WEATHER_API', c_outbound_service TYPE if_com_outbound_api_factory=>ty_service_id VALUE 'Z_WEATHER_OS_REST'.ENDCLASS.
CLASS zcl_weather_api IMPLEMENTATION. METHOD get_current_weather. DATA lo_client TYPE REF TO if_web_http_client.
TRY. " 1. Recuperer le Communication Arrangement DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = c_comm_scenario service_id = c_outbound_service ).
" 2. Creer le HTTP Client lo_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
" 3. Configurer la requete DATA(lo_request) = lo_client->get_http_request( ). lo_request->set_uri_path( |/weather?city={ cl_web_http_utility=>escape_url( iv_city ) }| ). lo_request->set_header_field( i_name = 'Accept" i_value = 'application/json" ).
" 4. Executer la requete DATA(lo_response) = lo_client->execute( if_web_http_client=>get ). DATA(lv_status) = lo_response->get_status( )-code.
" 5. Traiter la reponse IF lv_status = 200. DATA(lv_json) = lo_response->get_text( ).
/ui2/cl_json=>deserialize( EXPORTING json = lv_json pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = rs_result ). ELSE. " Gestion des erreurs DATA(lv_error_body) = lo_response->get_text( ). RAISE EXCEPTION TYPE cx_web_http_client_error. ENDIF.
CATCH cx_http_dest_provider_error cx_web_http_client_error. RAISE.
CLEANUP. IF lo_client IS BOUND. lo_client->close( ). ENDIF. ENDTRY. ENDMETHOD.ENDCLASS.Parsing et mapping JSON
Structures JSON complexes
" Structure de reponse APITYPES: BEGIN OF ty_coord, lat TYPE decfloat16, lon TYPE decfloat16, END OF ty_coord,
BEGIN OF ty_weather_detail, id TYPE i, main TYPE string, description TYPE string, icon TYPE string, END OF ty_weather_detail, tt_weather_details TYPE STANDARD TABLE OF ty_weather_detail WITH EMPTY KEY,
BEGIN OF ty_main, temp TYPE decfloat16, feels_like TYPE decfloat16, temp_min TYPE decfloat16, temp_max TYPE decfloat16, pressure TYPE i, humidity TYPE i, END OF ty_main,
BEGIN OF ty_full_response, coord TYPE ty_coord, weather TYPE tt_weather_details, main TYPE ty_main, name TYPE string, cod TYPE i, END OF ty_full_response.
METHOD parse_weather_response. DATA ls_response TYPE ty_full_response.
" Parser le JSON avec structures imbriquees /ui2/cl_json=>deserialize( EXPORTING json = iv_json pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
" Mapper vers la structure cible rs_weather = VALUE #( location = ls_response-name temperature = ls_response-main-temp humidity = ls_response-main-humidity condition = VALUE #( ls_response-weather[ 1 ]-description OPTIONAL ) latitude = ls_response-coord-lat longitude = ls_response-coord-lon ).ENDMETHOD.Mapping de noms pour conventions differentes
" L'API utilise snake_case, ABAP utilise camelCaseTYPES: BEGIN OF ty_api_response, user_id TYPE string, " API: user_id first_name TYPE string, " API: first_name last_name TYPE string, " API: last_name email_addr TYPE string, " API: email_addr created_at TYPE string, " API: created_at END OF ty_api_response.
METHOD deserialize_with_mapping. " pretty_mode-extended pour le mapping snake_case vers ABAP /ui2/cl_json=>deserialize( EXPORTING json = iv_json pretty_name = /ui2/cl_json=>pretty_mode-extended CHANGING data = rs_result ).ENDMETHOD.Requete POST avec body JSON
Envoyer des donnees vers une API externe
CLASS zcl_order_api DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. TYPES: BEGIN OF ty_order_item, product_id TYPE string, quantity TYPE i, price TYPE decfloat16, END OF ty_order_item, tt_order_items TYPE STANDARD TABLE OF ty_order_item WITH EMPTY KEY,
BEGIN OF ty_order_request, customer_id TYPE string, order_date TYPE string, shipping_addr TYPE string, items TYPE tt_order_items, END OF ty_order_request,
BEGIN OF ty_order_response, order_id TYPE string, status TYPE string, total_amount TYPE decfloat16, estimated_date TYPE string, END OF ty_order_response.
METHODS create_order IMPORTING is_order TYPE ty_order_request RETURNING VALUE(rs_result) TYPE ty_order_response RAISING cx_http_dest_provider_error cx_web_http_client_error.ENDCLASS.
CLASS zcl_order_api IMPLEMENTATION. METHOD create_order. DATA lo_client TYPE REF TO if_web_http_client.
TRY. " Recuperer la destination DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_ORDER_API" service_id = 'Z_ORDER_OS_REST" ).
" Creer le HTTP Client lo_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
" Body de la requete en JSON DATA(lv_json_body) = /ui2/cl_json=>serialize( data = is_order compress = abap_true pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
" Configurer la requete DATA(lo_request) = lo_client->get_http_request( ). lo_request->set_uri_path( '/orders' ). lo_request->set_header_field( i_name = 'Content-Type" i_value = 'application/json" ). lo_request->set_header_field( i_name = 'Accept" i_value = 'application/json" ). lo_request->set_text( lv_json_body ).
" Executer le POST DATA(lo_response) = lo_client->execute( if_web_http_client=>post ). DATA(lv_status) = lo_response->get_status( )-code.
" Traiter la reponse IF lv_status = 201 OR lv_status = 200. /ui2/cl_json=>deserialize( EXPORTING json = lo_response->get_text( ) pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = rs_result ). ELSE. RAISE EXCEPTION TYPE cx_web_http_client_error. ENDIF.
CLEANUP. IF lo_client IS BOUND. lo_client->close( ). ENDIF. ENDTRY. ENDMETHOD.ENDCLASS.Authentification
Authentification par cle API
METHOD call_with_api_key. DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_API_SCENARIO" service_id = 'Z_API_SERVICE" ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
DATA(lo_request) = lo_client->get_http_request( ).
" Cle API dans le header lo_request->set_header_field( i_name = 'X-API-Key" i_value = lv_api_key " Depuis le Secure Store ou la Destination ).
" Ou comme parametre de requete lo_request->set_uri_path( |/data?api_key={ lv_api_key }| ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ). lo_client->close( ).ENDMETHOD.OAuth 2.0 Client Credentials
OAuth est gere automatiquement via le Communication Arrangement :
Configuration du Communication System :┌────────────────────────────────────────┐│ Parametres OAuth 2.0 │├────────────────────────────────────────┤│ Token Endpoint: /oauth/token ││ Client ID: my-client-id ││ Client Secret: ******** ││ Scope: api.read api.write │└────────────────────────────────────────┘" Avec OAuth, le token est automatiquement obtenu et renouveleMETHOD call_with_oauth. " Le Communication Arrangement contient la configuration OAuth DATA(lo_destination) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_OAUTH_API" service_id = 'Z_OAUTH_SERVICE" ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( i_destination = lo_destination ).
" Le header Authorization est ajoute automatiquement DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).
lo_client->close( ).ENDMETHOD.Definir manuellement un Bearer Token
METHOD call_with_bearer_token. DATA(lo_request) = lo_client->get_http_request( ).
" Bearer Token depuis un appel d'authentification precedent lo_request->set_header_field( i_name = 'Authorization" i_value = |Bearer { lv_access_token }| ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>get ).ENDMETHOD.Gestion des erreurs et logique de retry
Classe d’exception robuste
CLASS zcx_external_api_error DEFINITION PUBLIC INHERITING FROM cx_static_check CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_t100_message. INTERFACES if_t100_dyn_msg.
CONSTANTS: BEGIN OF connection_failed, msgid TYPE symsgid VALUE 'Z_API', msgno TYPE symsgno VALUE '001', attr1 TYPE scx_attrname VALUE 'MV_URL', attr2 TYPE scx_attrname VALUE '', attr3 TYPE scx_attrname VALUE '', attr4 TYPE scx_attrname VALUE '', END OF connection_failed,
BEGIN OF http_error, msgid TYPE symsgid VALUE 'Z_API', msgno TYPE symsgno VALUE '002', attr1 TYPE scx_attrname VALUE 'MV_STATUS_CODE', attr2 TYPE scx_attrname VALUE 'MV_STATUS_TEXT', attr3 TYPE scx_attrname VALUE '', attr4 TYPE scx_attrname VALUE '', END OF http_error,
BEGIN OF timeout, msgid TYPE symsgid VALUE 'Z_API', msgno TYPE symsgno VALUE '003', attr1 TYPE scx_attrname VALUE 'MV_URL', attr2 TYPE scx_attrname VALUE '', attr3 TYPE scx_attrname VALUE '', attr4 TYPE scx_attrname VALUE '', END OF timeout,
BEGIN OF rate_limit_exceeded, msgid TYPE symsgid VALUE 'Z_API', msgno TYPE symsgno VALUE '004', attr1 TYPE scx_attrname VALUE 'MV_RETRY_AFTER', attr2 TYPE scx_attrname VALUE '', attr3 TYPE scx_attrname VALUE '', attr4 TYPE scx_attrname VALUE '', END OF rate_limit_exceeded.
DATA: mv_url TYPE string, mv_status_code TYPE i, mv_status_text TYPE string, mv_retry_after TYPE i, mv_is_retryable TYPE abap_bool.
METHODS constructor IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL previous LIKE previous OPTIONAL iv_url TYPE string OPTIONAL iv_status TYPE i OPTIONAL iv_text TYPE string OPTIONAL iv_retryable TYPE abap_bool DEFAULT abap_false.
METHODS is_retryable RETURNING VALUE(rv_retryable) TYPE abap_bool.ENDCLASS.
CLASS zcx_external_api_error IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ).
mv_url = iv_url. mv_status_code = iv_status. mv_status_text = iv_text. mv_is_retryable = iv_retryable.
IF textid IS INITIAL. if_t100_message~t100key = if_t100_message=>default_textid. ELSE. if_t100_message~t100key = textid. ENDIF. ENDMETHOD.
METHOD is_retryable. rv_retryable = mv_is_retryable. ENDMETHOD.ENDCLASS.Logique de retry avec Exponential Backoff
CLASS zcl_api_client_with_retry DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. CONSTANTS: c_max_retries TYPE i VALUE 3, c_initial_delay TYPE i VALUE 1000, " Millisecondes c_max_delay TYPE i VALUE 30000. " Millisecondes
METHODS execute_with_retry IMPORTING io_client TYPE REF TO if_web_http_client iv_method TYPE i DEFAULT if_web_http_client=>get RETURNING VALUE(ro_response) TYPE REF TO if_web_http_response RAISING zcx_external_api_error.
PRIVATE SECTION. METHODS is_retryable_status IMPORTING iv_status TYPE i RETURNING VALUE(rv_retryable) TYPE abap_bool.
METHODS wait_with_backoff IMPORTING iv_attempt TYPE i.ENDCLASS.
CLASS zcl_api_client_with_retry IMPLEMENTATION. METHOD execute_with_retry. DATA lv_attempts TYPE i. DATA lx_last_error TYPE REF TO zcx_external_api_error.
WHILE lv_attempts < c_max_retries. lv_attempts = lv_attempts + 1.
TRY. " Executer la requete ro_response = io_client->execute( iv_method ). DATA(lv_status) = ro_response->get_status( )-code.
" Reponse reussie IF lv_status >= 200 AND lv_status < 300. RETURN. ENDIF.
" Rate Limit IF lv_status = 429. " Evaluer le header Retry-After DATA(lv_retry_after) = ro_response->get_header_field( 'Retry-After' ). wait_with_backoff( lv_attempts ). CONTINUE. ENDIF.
" Erreurs serveur (5xx) - retry IF is_retryable_status( lv_status ). IF lv_attempts < c_max_retries. wait_with_backoff( lv_attempts ). CONTINUE. ENDIF. ENDIF.
" Erreurs client (4xx) - pas de retry RAISE EXCEPTION TYPE zcx_external_api_error EXPORTING textid = zcx_external_api_error=>http_error iv_status = lv_status iv_text = ro_response->get_status( )-reason iv_retryable = abap_false.
CATCH cx_web_http_client_error INTO DATA(lx_http). " Erreur reseau - retry IF lv_attempts < c_max_retries. wait_with_backoff( lv_attempts ). CONTINUE. ENDIF.
RAISE EXCEPTION TYPE zcx_external_api_error EXPORTING textid = zcx_external_api_error=>connection_failed previous = lx_http iv_retryable = abap_true. ENDTRY. ENDWHILE.
" Max Retries atteint RAISE EXCEPTION TYPE zcx_external_api_error EXPORTING textid = zcx_external_api_error=>connection_failed iv_retryable = abap_false. ENDMETHOD.
METHOD is_retryable_status. " Erreurs serveur 5xx et 429 Rate Limit rv_retryable = xsdbool( iv_status = 429 OR iv_status = 500 OR iv_status = 502 OR iv_status = 503 OR iv_status = 504 ). ENDMETHOD.
METHOD wait_with_backoff. " Exponential Backoff : delay = initial_delay * 2^(attempt-1) DATA(lv_delay) = c_initial_delay * ipow( base = 2 exp = iv_attempt - 1 ).
" Limiter au maximum IF lv_delay > c_max_delay. lv_delay = c_max_delay. ENDIF.
" Attendre cl_abap_session=>sleep( lv_delay ). ENDMETHOD.ENDCLASS.Integration dans RAP
Determination avec appel API
CLASS lhc_order DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS calculate_shipping FOR DETERMINE ON SAVE IMPORTING keys FOR Order~CalculateShipping.ENDCLASS.
CLASS lhc_order IMPLEMENTATION. METHOD calculate_shipping. " Lire les commandes READ ENTITIES OF zi_order IN LOCAL MODE ENTITY Order FIELDS ( ShippingAddress PostalCode Country Weight ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_orders).
" Appeler l'API de livraison externe DATA(lo_shipping_api) = NEW zcl_shipping_api( ).
LOOP AT lt_orders INTO DATA(ls_order). TRY. " Recuperer les frais de livraison depuis le service externe DATA(ls_shipping) = lo_shipping_api->calculate_shipping( iv_country = ls_order-Country iv_postal_code = ls_order-PostalCode iv_weight = ls_order-Weight ).
" Mettre a jour la commande MODIFY ENTITIES OF zi_order IN LOCAL MODE ENTITY Order UPDATE FIELDS ( ShippingCost EstimatedDelivery ) WITH VALUE #( ( %tky = ls_order-%tky ShippingCost = ls_shipping-cost EstimatedDelivery = ls_shipping-delivery_date ) ).
CATCH zcx_external_api_error INTO DATA(lx_error). " Ajouter l'erreur comme message APPEND VALUE #( %tky = ls_order-%tky %msg = new_message_with_text( text = lx_error->get_text( ) ) %element-ShippingCost = if_abap_behv=>mk-on ) TO reported-order. ENDTRY. ENDLOOP. ENDMETHOD.ENDCLASS.Action avec integration API
CLASS lhc_product DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS refresh_stock FOR MODIFY IMPORTING keys FOR ACTION Product~RefreshStock RESULT result.ENDCLASS.
CLASS lhc_product IMPLEMENTATION. METHOD refresh_stock. " Lire les produits READ ENTITIES OF zi_product IN LOCAL MODE ENTITY Product FIELDS ( ProductId ExternalId ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_products).
" Appeler l'API d'inventaire externe DATA(lo_inventory_api) = NEW zcl_inventory_api( ).
" Requete batch pour tous les produits DATA lt_product_ids TYPE string_table. LOOP AT lt_products INTO DATA(ls_product). APPEND ls_product-ExternalId TO lt_product_ids. ENDLOOP.
TRY. " Recuperer les niveaux de stock DATA(lt_stock) = lo_inventory_api->get_stock_levels( it_product_ids = lt_product_ids ).
" Mettre a jour les produits LOOP AT lt_products INTO ls_product. DATA(ls_stock) = VALUE #( lt_stock[ product_id = ls_product-ExternalId ] OPTIONAL ).
IF ls_stock IS NOT INITIAL. MODIFY ENTITIES OF zi_product IN LOCAL MODE ENTITY Product UPDATE FIELDS ( StockQuantity LastStockUpdate ) WITH VALUE #( ( %tky = ls_product-%tky StockQuantity = ls_stock-quantity LastStockUpdate = utclong_current( ) ) ). ENDIF. ENDLOOP.
" Retourner le resultat READ ENTITIES OF zi_product IN LOCAL MODE ENTITY Product ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(lt_updated).
result = VALUE #( FOR wa IN lt_updated ( %tky = wa-%tky %param = wa ) ).
CATCH zcx_external_api_error INTO DATA(lx_error). LOOP AT keys INTO DATA(ls_key). APPEND VALUE #( %tky = ls_key-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = lx_error->get_text( ) ) ) TO reported-product. ENDLOOP. ENDTRY. ENDMETHOD.ENDCLASS.Bonnes pratiques
A FAIRE
| Recommandation | Description |
|---|---|
| Communication Arrangements | Gerer les credentials de maniere centralisee, jamais dans le code |
| Logique de retry | Exponential Backoff pour les erreurs transitoires |
| Definir les timeouts | Configurer des timeouts appropries |
| Appeler close() | Toujours fermer le HTTP Client (meme en cas d’erreur) |
| Gestion des erreurs | Exceptions specifiques pour les erreurs API |
| Logging | Journaliser les appels API pour le debogage |
| Requetes batch | Plusieurs enregistrements en un seul appel si possible |
A NE PAS FAIRE
| A eviter | Raison |
|---|---|
| Credentials dans le code | Risque de securite, difficile a modifier |
| Retry illimite | Peut surcharger le systeme |
| Appels longs synchrones | Bloque l’UI, risque de timeout |
| Erreurs ignorees | Conduit a des donnees incoherentes |
| Validation manquante | Toujours valider les reponses API |
Conseils de performance
" 1. Reutilisation de connexion - Reutiliser le clientDATA: go_client TYPE REF TO if_web_http_client.
METHOD get_or_create_client. IF go_client IS NOT BOUND. DATA(lo_dest) = cl_http_destination_provider=>create_by_comm_arrangement( comm_scenario = 'Z_API" service_id = 'Z_SERVICE" ). go_client = cl_web_http_client_manager=>create_by_http_destination( lo_dest ). ENDIF. ro_client = go_client.ENDMETHOD.
" 2. Batch au lieu de requetes individuellesMETHOD fetch_multiple_products. " MAUVAIS : N requetes individuelles LOOP AT it_product_ids INTO DATA(lv_id). APPEND fetch_single( lv_id ) TO rt_products. ENDLOOP.
" BON : Une requete batch DATA(lv_ids) = concat_lines_of( table = it_product_ids sep = ',' ). rt_products = fetch_batch( lv_ids ).ENDMETHOD.
" 3. Cache pour les donnees statiquesCLASS-DATA: gt_cache TYPE STANDARD TABLE OF ty_product, gv_cache_time TYPE timestamp.
METHOD get_products_cached. " Cache valide 5 minutes DATA(lv_now) = utclong_current( ). DATA(lv_age) = cl_abap_tstmp=>subtract( tstmp1 = lv_now tstmp2 = gv_cache_time ).
IF gv_cache_time IS INITIAL OR lv_age > 300. gt_cache = fetch_from_api( ). gv_cache_time = lv_now. ENDIF.
rt_products = gt_cache.ENDMETHOD.Depannage
| Probleme | Cause possible | Solution |
|---|---|---|
| 401 Unauthorized | Token expire, credentials incorrects | Verifier le Communication Arrangement |
| 403 Forbidden | Permissions manquantes | Verifier le scope API |
| 404 Not Found | Chemin incorrect | Valider l’URL et le chemin |
| 429 Too Many Requests | Rate Limit atteint | Respecter le header Retry-After |
| 500 Server Error | Probleme backend | Verifier les logs, implementer le retry |
| Connection Timeout | Reseau, Firewall | Verifier le SAP Cloud Connector |
| SSL Certificate Error | Certificat invalide | Configurer le Trust Store |
Sujets connexes
- RAP avec Custom Entities - Integrer des donnees externes dans RAP
- SAP Destination Service - Configurer les destinations
- Traitement JSON - Serialisation et parsing JSON
- HTTP Client - Bases HTTP dans ABAP
- Classes Wrapper - Encapsuler proprement les APIs externes