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 Interface IF_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