Eigene REST API als SICF-Service mit Superklassen CL REST HTTP HANDLER und CL REST RESOURCE erstellen

Aus SAP Wiki ツ
Version vom 30. Januar 2026, 18:07 Uhr von M1ch3lde (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „Kategorie: Codeschnipsel Eine Erstellung einer REST API wird an einem Beispiel erklärt.<br /> Das Geschäftsobjekt ist der Geschäftspartner.<br /> Das Ziel ist es mit einem Aufruf einen beliebigen Geschäftspartner zu lesen und genau einen Geschäftspartner anzulegen.<br /> Für das Lesen eines Geschäftspartners wird einfach ein SELECT SINGLE auf I_BUSINESSPARTNER gemacht.<br /> Für das Anlegen wird eine Y-Klasse namens "YCL_BP" genutzt. In R…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)


Eine Erstellung einer REST API wird an einem Beispiel erklärt.
Das Geschäftsobjekt ist der Geschäftspartner.
Das Ziel ist es mit einem Aufruf einen beliebigen Geschäftspartner zu lesen und genau einen Geschäftspartner anzulegen.
Für das Lesen eines Geschäftspartners wird einfach ein SELECT SINGLE auf I_BUSINESSPARTNER gemacht.
Für das Anlegen wird eine Y-Klasse namens "YCL_BP" genutzt. In Rahmen des Beispiels wird nur der Businesspartner mit allgemeinen Daten angelegt, daher kann selber der BAPI für einen Eigentest genommen werden.

Zu beachten ist, dass der Code evtl. nicht bulletproof ist. Es gilt sicher Fälle abzudecken, wie der Aufruf der API passiert und mit Sicherheit damit kein Unfug getrieben wird.

Übersicht der Objekte

Superklassen

  • CL_REST_HTTP_HANDLER
  • CL_REST_RESOURCE

Unterklassen

  • YCL_BP_REST
  • YCL_BP_REST_RESOURCE

BAPI

SICF

  • Pfad: default_host
    • Service-Name: ybp
      • Handler-Liste
        • Nr. 1 : YCL_BP_REST

Anzulegende Klassen

YCL_BP_REST

CLASS ycl_bp_rest DEFINITION
  PUBLIC
  INHERITING FROM cl_rest_http_handler
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    METHODS: if_rest_application~get_root_handler REDEFINITION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS ycl_bp_rest IMPLEMENTATION.
  METHOD if_rest_application~get_root_handler.
   DATA(lo_router) = NEW cl_rest_router(  ).
   lo_router->attach( iv_template = '/ybp' iv_handler_class = 'YCL_BP_REST_RESOURCE' ).
   ro_root_handler = lo_router.
  ENDMETHOD.

ENDCLASS.

YCL_BP_REST_RESOURCE

CLASS ycl_bp_rest_resource DEFINITION
  PUBLIC
  INHERITING FROM cl_rest_resource
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    METHODS if_rest_resource~get REDEFINITION.
    METHODS if_rest_resource~post REDEFINITION.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS ycl_bp_rest_resource IMPLEMENTATION.
  METHOD if_rest_resource~get.

    IF mo_request->get_uri_query_parameter( iv_name = 'createperson' ) IS NOT INITIAL.
      RETURN.
    ENDIF.

    IF mo_request->get_uri_query_parameter( iv_name = 'bpnumber' ) IS NOT INITIAL.

      DATA lv_bp_no TYPE I_BusinessPartner-BusinessPartner.
      lv_bp_no = mo_request->get_uri_query_parameter( iv_name = 'bpnumber' ).
      SELECT SINGLE FROM I_BusinessPartner
      FIELDS *
      WHERE BusinessPartner = @lv_bp_no
      INTO @DATA(ls_bp).
      IF sy-subrc = 0.
        DATA lv_data TYPE string.
        lv_data = /ui2/cl_json=>serialize(
         EXPORTING
           data             = ls_bp
        ).

        mo_response->create_entity( )->set_string_data( iv_data = lv_data ).
        mo_response->create_entity( )->set_content_type( if_rest_media_type=>gc_appl_json ).
        mo_response->set_status( cl_rest_status_code=>gc_success_ok ).
      ELSE.
        mo_response->create_entity( )->set_string_data( iv_data = '{"error":"Datarecord not found"}' ).
        mo_response->set_header_field( iv_name  = 'Content-Type' iv_value = if_rest_media_type=>gc_appl_json ).
        mo_response->set_status( cl_rest_status_code=>gc_client_error_not_found ).
      ENDIF.

    ELSE.
      RAISE EXCEPTION TYPE cx_rest_resource_exception
        EXPORTING
          status_code    = cl_rest_status_code=>gc_client_error_bad_request
          request_method = if_rest_request=>gc_method_get.
    ENDIF.
  ENDMETHOD.

  METHOD if_rest_resource~post.

        IF mo_request->get_uri_query_parameter( iv_name = 'createperson' ) <> 'true'.
          RAISE EXCEPTION TYPE cx_rest_resource_exception
            EXPORTING
              status_code    = cl_rest_status_code=>gc_client_error_bad_request
              request_method = if_rest_request=>gc_method_post.
        ENDIF.

        DATA ls_person TYPE ycl_bp=>ts_person_data.
        DATA(lv_request_body) = mo_request->get_entity(  )->get_string_data(  ).
        /ui2/cl_json=>deserialize( EXPORTING json = lv_request_body
                                   CHANGING  data = ls_person ).
        IF ls_person-firstname IS INITIAL.
          RAISE EXCEPTION TYPE cx_rest_resource_exception
            EXPORTING
              status_code    = cl_rest_status_code=>gc_client_error_bad_request
              request_method = if_rest_request=>gc_method_post.
        ENDIF.

    TRY.

        DATA(lo_bp) = NEW ycl_bp( ).

        lo_bp->set_bp_person_data(
          iv_title                      = ls_person-title
          iv_firstname                  = ls_person-firstname
          iv_lastname                   = ls_person-lastname
          iv_gender                     = ls_person-gender
          iv_correspondencelanguagecode = to_upper( ls_person-correspondencelanguagecode )
          iv_street                     = ls_person-street
          iv_postalcode                 = ls_person-postalcode
          iv_city                       = ls_person-city
          iv_county                     = ls_person-county
          iv_country                    = to_upper( ls_person-country )
          iv_language                   = to_upper( ls_person-language )
          iv_searchterm1                = |{ ls_person-firstname } { ls_person-lastname }|
          iv_bpgrouping                 = ls_person-bpgrouping
        ).

        lo_bp->create_bp_with_bapi( iv_wait_after_commit = abap_true ).


        mo_response->set_header_field( iv_name  = 'Content-Type' iv_value = if_rest_media_type=>gc_appl_json ).

        IF lines( lo_bp->get_protocol( iv_only_errors = abap_true ) ) > 0.
          mo_response->set_status( cl_rest_status_code=>gc_client_error_not_found ).
          mo_response->create_entity( )->set_string_data( iv_data = '{"error":"Error creating Businesspartner/Person"}' ).
        ELSE.
          mo_response->set_status( cl_rest_status_code=>gc_success_ok ).
          mo_response->create_entity( )->set_string_data( iv_data = '{"BusinessPartnerPerson":"' && lo_bp->get_bp_no( ) && '"}' ).
        ENDIF.

      CATCH cx_fiil_error INTO DATA(lx_bp_error).
        RAISE EXCEPTION TYPE cx_rest_resource_exception
          EXPORTING
            status_code    = cl_rest_status_code=>gc_client_error_bad_request
            request_method = if_rest_request=>gc_method_post.
    ENDTRY.

  ENDMETHOD.

ENDCLASS.

Aufruf mit /IWFND/GW_CLIENT

GET

HTTP-Method: GET Request-Uri: http://...:.../ybp/ybp?bpnumber=9980000471

HTTP Request

  • Header Name
    • x-csrf-token: blank (Nach Aufruf von GET kopieren für Methode POST)
    • if-match: *

HTTP Response

  • Header Name
    • ~status_code: Statuscode 200 für Erfolg oder bei Fehler einer der 4** Statuscodes, die im Coding festgelegt wurden

Body

{
 "BUSINESSPARTNER" : "9980000471",
 "BUSINESSPARTNERCATEGORY : "1",
 ...
}

POST

HTTP-Method: POST Request-Uri: http://...:.../ybp/ybp?createperson=true

HTTP Request

  • Header Name
    • x-csrf-token: blank (Nach Aufruf von GET kopieren für Methode POST)
    • if-match: sE1kukdskadka43sd4556wadasda (der Token, den man vom GET bekommen kann)

HTTP Response

  • Header Name
    • ~status_code: Statuscode 200 für Erfolg oder bei Fehler einer der 4** Statuscodes, die im Coding festgelegt wurden

Body

  • Ausgabe als JSON Format:
{
 "BusinessPartnerPerson" : "9980000471"
}

Quellen

Das Wissen um die technische Erstellung der REST API stammt von Videos von https://www.youtube.com/@CustAndCode
Lasst dem österreichischen Kollegen einen Abonnement da ツ


Dieses Wiki wird privat in Freizeit nach bestem Wissen und Gewissen gepflegt und dient primär als eigene Wissenssammlung für die tägliche Arbeit im SAP-ERP-Umfeld.
Alle dargestellten Softwareprodukte, auch in Form von Screenshots, sind Eigentum der SAP SE. Ihre Marken, vgl. Link, sind u.a.: SAP®, ABAP®, SAP Fiori®, SAP HANA®, SAP S/4HANA®, SAP S/4HANA® Cloud