Piyush Philip auf sap.com hat eine simple Möglichkeit beschrieben, wie man in ABAP einen REST-Service mit den entsprechenden CRUD-Methoden implementieren kann. Dazu ist im Wesentlichen nur eine eigene Handler-Klasse zu implementieren, die von IF_HTTP_EXTENSION
erbt. Diese Handler-Klasse wird von einem Service des ICF gerufen.
- SE80 -> Neue Klasse anlegen
- In der Klasse im Reiter
Interfaces
: vom InterfaceIF_HTTP_EXTENSION
erben - die Interface-Methode
IF_HTTP_EXTENSION~HANDLE_REQUEST
implementieren (implementiert nur REST, kein OData-Sevice!)METHOD if_http_extension~handle_request. * Typen TYPES: BEGIN OF ty_json_request, param1 TYPE char64, param2 TYPE char64, END OF ty_json_request. TYPES: BEGIN OF ty_json_response, success TYPE string, msg TYPE string, operation TYPE string, END OF ty_json_response. * Variablen DATA: rv_response TYPE ty_json_response. DATA: it_path_info TYPE stringtab. DATA: it_query_strings TYPE stringtab. * Header Fields auslesen DATA: it_header_fields TYPE tihttpnvp. server->request->get_header_fields( CHANGING fields = it_header_fields ). * Request Methode (POST, GET, PUT, DELETE ...) DATA(lv_request_method) = server->request->get_header_field( name = '~request_method' ). * URL Pathinfo DATA(lv_path_info) = server->request->get_header_field( name = '~path_info' ). * erstes '/' entfernen SHIFT lv_path_info LEFT BY 1 PLACES. SPLIT lv_path_info AT '/' INTO TABLE it_path_info. * URL Parameter (Query Strings) für Auswertung DATA(lv_query_string) = server->request->get_header_field( name = '~query_string' ). SPLIT lv_query_string AT '&' INTO TABLE it_query_strings. * Request Methoden behandeln CASE lv_request_method. * C (Create) WHEN 'POST'. * Beispiel: per Request übermittelte JSON-Daten auslesen und behandeln * Content-Typ auslesen DATA(lv_request_content_type) = server->request->get_content_type( ). * Wenn Content-Typ JSON IF lv_request_content_type CP if_rest_media_type=>gc_appl_json. * JSON-Daten auslesen und nach ABAP-Typ konvertieren -> Parameternamen müssen übereinstimmen, sonst HTTP 500! DATA(lv_request_cdata) = server->request->get_cdata( ). DATA: lv_request_abap TYPE ty_json_request. TRY. /ui2/cl_json=>deserialize( EXPORTING json = lv_request_cdata pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = lv_request_abap ). CATCH cx_root INTO DATA(e_txt). MESSAGE e_txt->get_text( ) TYPE 'S' DISPLAY LIKE 'E'. ENDTRY. rv_response = VALUE #( success = 'true' msg = lv_request_abap-param1 && ' | ' && lv_request_abap-param2 operation = lv_request_method ). ELSE. rv_response = VALUE #( success = 'false' msg = 'Request content type must be application/json' operation = lv_request_method ). ENDIF. * R (Read) WHEN 'GET'. DATA(lv_param) = server->request->get_form_field( 'param' ). rv_response = VALUE #( success = 'true' msg = lv_param operation = lv_request_method ). * U (Update) WHEN 'PUT'. rv_response = VALUE #( success = 'true' msg = '' operation = lv_request_method ). * D (Delete) WHEN 'DELETE'. rv_response = VALUE #( success = 'true' msg = '' operation = lv_request_method ). * unerlaubte Methoden abfangen WHEN OTHERS. * Fehlercode 405 zurückgeben server->response->set_status( code = cl_rest_status_code=>gc_client_error_meth_not_allwd reason = 'method not allowed' ). server->response->set_content_type( if_rest_media_type=>gc_appl_json ). server->response->set_header_field( name = if_http_header_fields=>allow value = 'POST,GET,PUT,DELETE' ). rv_response = VALUE #( success = 'false' msg = 'error' operation = lv_request_method ). ENDCASE. * wenn erfolgreich, dann Wert zurückgeben IF rv_response-success = 'true'. * HTTP-Status 200 server->response->set_status( code = cl_rest_status_code=>gc_success_ok reason = 'Ok.' ). * application/json server->response->set_content_type( if_rest_media_type=>gc_appl_json ). * Service-Response als JSON zurückgeben server->response->set_cdata( data = /ui2/cl_json=>serialize( data = rv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case ) ). ENDIF. ENDMETHOD.
- SICF -> neue ICF-Node (Sub-Element) unterhalb
default_host -> sap -> bc
als neuen unabhängigen Service anlegen - in der Handlerliste des Service die erstellte Klasse als “Handler” angeben
- auf die neue ICF-Node rechtsklicken ->
Service aktivieren
- auf die neue ICF-Node rechtsklicken ->
Service testen
- URL aus Browserfenster kopieren (
http://domain.de/sap/bc/servicename?sap-client=900
) - im Browser mir einem Rest-Plugin (FireFox-Prugin:
Rested
) testen
Links
- https://blogs.sap.com/2018/10/31/a-simple-rest-web-service-from-ecc-called-from-a-html5-screen/
- https://blogs.sap.com/2012/12/07/building-a-crud-application-with-sapui5-and-icf-restjson-service-part-1/
- https://blogs.sap.com/2013/01/24/developing-a-rest-api-in-abap/
- https://medium.com/pacroy/developing-apis-in-abap-just-rest-not-odata-d91cf899f7d3
- https://blogs.sap.com/2013/05/16/usage-of-the-abap-rest-library-sapbasis-740/
- https://www.linkedin.com/pulse/create-json-rest-service-from-sap-back-end-louis-rossi-mundecke
- REST Interfaces and Classes
- The GET Method
- The POST Method
- The PUT Method
- The DELETE Method