
BTP - Zugriffsmethoden On-Premise (OData)
In diesem Artikel schauen wir uns die anderen Zugriffmethoden auf einen OData Service über die Proxy Klassen an.
Inhaltsverzeichnis
Im letzten Artikel haben wir uns angeschaut, wie wir einen OData Service im ABAP Environment zur Verfügung stellen und zum ersten Mal auch aufrufen. Neben dem Holen von Daten gibt es aber auch andere Szenarien, mit der API im Backend zu arbeiten, diese wollen wir uns in diesem Artikel näher anschauen.
Einleitung
Wie bereits im letzten Artikel angesprochen, müssen wir vor dem Zugriff eine Proxy Klasse erzeugen, über die wir unser Proxy Objekt erzeugen können, um auf das Backend zugreifen zu können. Wir verwenden in diesem Fall wieder eine Destination aus dem Destination Service und erzeugen das Objekt in einer eigenen Methode GET_PROXY. Diese Methode verwenden wir in allen folgenden Beispielen:
DATA(lo_destination) = cl_http_destination_provider=>create_by_cloud_destination(
i_name = c_destination
i_authn_mode = if_a4c_cp_service=>service_specific
).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
ro_result = cl_web_odata_client_factory=>create_v2_remote_proxy(
EXPORTING
iv_service_definition_name = 'ZBS_DEMO_RAP_ONPREM_ODATA'
io_http_client = lo_client
iv_relative_service_root = '/sap/opu/odata/sap/ZBS_API_COMPANY_NAMES_O2' ).
READ mit Filter
Beim letzten Zugriff hatten wir alle Daten der Schnittstelle gelesen, in diesem Beispiel wollen wir einmal einen Filter auf ein Feld anwenden, um nur eine Teilmenge der Daten zu lesen. Im ersten Schritt erstellen wir eine Range mit den entsprechenden Filtern und erzeugen dann ein Objekt zum Lesen. Im Anschluss erzeugen wir eine Filter-Factory und bauen einen Filter für den Zugriff auf.
DATA:
lt_r_branch TYPE RANGE OF zbs_rap_companynames-Branch,
lt_found TYPE STANDARD TABLE OF zbs_rap_companynames.
lt_r_branch = VALUE #( sign = 'I' option = 'EQ'
( low = 'Software' )
( low = 'Food' )
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_read( ).
" Create filter object
DATA(lo_filter_factory) = lo_request->create_filter_factory( ).
DATA(lo_filter) = lo_filter_factory->create_by_range( iv_property_path = 'BRANCH' it_range = lt_r_branch ).
lo_request->set_filter( lo_filter ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING et_business_data = lt_found ).
Es werden nun aus dem Backend die gefundenen Einträge in LT_FOUND zurückgegeben, diese entsprechen unserem angewandten Filter:
CREATE
Im zweiten Beispiel wollen wir einen neuen Datensatz On-Premise erzeugen. Dazu definieren wir uns eine Struktur mit den neuen Werten, der Schlüssel der Entität muss aber mindestens gefüllt sein. Dann erzeugen wir uns ein Objekt für die Anlage und übergeben die Daten. Am Ende führen wir die Anfrage per Execute aus.
DATA:
ls_created TYPE zbs_rap_companynames.
DATA(ls_new_company) = VALUE zbs_rap_companynames(
CompanyName = 'Gazprom'
Branch = 'Gas'
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_create( ).
lo_request->set_business_data( ls_new_company ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_created ).
Wenn wir uns die Tabelle im Data-Preview anschauen, wurde der neue Datensatz angelegt. Mit einer weiteren Leseabfrage, könnten wir dann die Daten ermitteln:
UPDATE
Den zuvor angelegten Datensatz wollen wir in diesem Schritt nun aktualisieren und eine Beschreibung mitgeben. Dazu definieren wir uns zwei Strukturen, eine für den Schlüssel und eine mit den Daten. Bevor wir das Update-Objekt erzeugen können, müssen wir über den Schlüssel navigieren. Beim Update setzen wir die HTTP Methode auf PUT. Zum Abschluss übergeben wir wieder die neuen Daten und führen die Anfrage aus.
DATA:
ls_updated TYPE zbs_rap_companynames.
DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).
DATA(ls_update_company) = VALUE zbs_rap_companynames(
companyname = 'Gazprom'
branch = 'Gas'
companydescription = `PJSC Gazprom is a Russian majority state-owned multinational energy corporation headquartered in the Lakhta Center in Saint Petersburg.`
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
)->navigate_with_key( ls_key
)->create_request_for_update( /iwbep/if_cp_request_update=>gcs_update_semantic-put
).
lo_request->set_business_data( ls_update_company ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_updated ).
In diesem Fall sind nun die Daten über den Data-Preview vollständig und wir sehen die befüllte Beschreibung im Backend System:
DELETE
Zum Abschluss wollen wir den Datensatz wieder aus dem System entfernen. In diesem Fall benötigen wir nur die Schlüssel-Struktur, navigieren über diese und erzeugen uns ein Objekt zum Löschen. Am Ende reicht das Ausführen der Abfrage und der Datensatz wird gelöscht.
DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
)->navigate_with_key( ls_key
)->create_request_for_delete(
).
lo_request->execute( ).
io_out->write( `Company deleted` ).
Vollständiges Beispiel
Hier noch einmal die vollständige Beispielklasse mit der Ausführung. Damit diese läuft, muss noch eine existierende Destination eingefügt werden und die API im Zielsystem laufen:
CLASS zcl_bs_demo_odata_actions DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
CONSTANTS:
c_destination TYPE string VALUE `<destination-service-id>`,
c_entity TYPE /iwbep/if_cp_runtime_types=>ty_entity_set_name VALUE 'COMPANYNAMES'.
METHODS:
get_proxy
RETURNING VALUE(ro_result) TYPE REF TO /iwbep/if_cp_client_proxy,
read_data_with_filter
IMPORTING
io_out TYPE REF TO if_oo_adt_classrun_out
RAISING
/iwbep/cx_gateway,
create_new_company
IMPORTING
io_out TYPE REF TO if_oo_adt_classrun_out
RAISING
/iwbep/cx_gateway,
update_company_description
IMPORTING
io_out TYPE REF TO if_oo_adt_classrun_out
RAISING
/iwbep/cx_gateway,
delete_company
IMPORTING
io_out TYPE REF TO if_oo_adt_classrun_out
RAISING
/iwbep/cx_gateway.
ENDCLASS.
CLASS zcl_bs_demo_odata_actions IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
TRY.
read_data_with_filter( out ).
create_new_company( out ).
update_company_description( out ).
delete_company( out ).
CATCH cx_root INTO DATA(lo_error).
out->write( lo_error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD get_proxy.
TRY.
DATA(lo_destination) = cl_http_destination_provider=>create_by_cloud_destination(
i_name = c_destination
i_authn_mode = if_a4c_cp_service=>service_specific
).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination( lo_destination ).
ro_result = cl_web_odata_client_factory=>create_v2_remote_proxy(
EXPORTING
iv_service_definition_name = 'ZBS_DEMO_RAP_ONPREM_ODATA'
io_http_client = lo_client
iv_relative_service_root = '/sap/opu/odata/sap/ZBS_API_COMPANY_NAMES_O2' ).
CATCH cx_root.
ENDTRY.
ENDMETHOD.
METHOD read_data_with_filter.
DATA:
lt_r_branch TYPE RANGE OF zbs_rap_companynames-Branch,
lt_found TYPE STANDARD TABLE OF zbs_rap_companynames.
lt_r_branch = VALUE #( sign = 'I' option = 'EQ'
( low = 'Software' )
( low = 'Food' )
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_read( ).
DATA(lo_filter_factory) = lo_request->create_filter_factory( ).
DATA(lo_filter) = lo_filter_factory->create_by_range( iv_property_path = 'BRANCH' it_range = lt_r_branch ).
lo_request->set_filter( lo_filter ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING et_business_data = lt_found ).
io_out->write( `Read with filter active:` ).
io_out->write( lt_found ).
ENDMETHOD.
METHOD create_new_company.
DATA:
ls_created TYPE zbs_rap_companynames.
DATA(ls_new_company) = VALUE zbs_rap_companynames(
CompanyName = 'Gazprom'
Branch = 'Gas'
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity )->create_request_for_create( ).
lo_request->set_business_data( ls_new_company ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_created ).
io_out->write( `Created new company:` ).
io_out->write( ls_created ).
ENDMETHOD.
METHOD update_company_description.
DATA:
ls_updated TYPE zbs_rap_companynames.
DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).
DATA(ls_update_company) = VALUE zbs_rap_companynames(
companyname = 'Gazprom'
branch = 'Gas'
companydescription = `PJSC Gazprom is a Russian majority state-owned multinational energy corporation headquartered in the Lakhta Center in Saint Petersburg.`
).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
)->navigate_with_key( ls_key
)->create_request_for_update( /iwbep/if_cp_request_update=>gcs_update_semantic-put
).
lo_request->set_business_data( ls_update_company ).
DATA(lo_response) = lo_request->execute( ).
lo_response->get_business_data( IMPORTING es_business_data = ls_updated ).
io_out->write( `Updated company:` ).
io_out->write( ls_updated ).
ENDMETHOD.
METHOD delete_company.
DATA(ls_key) = VALUE zbs_rap_companynames( companyname = 'Gazprom' ).
DATA(lo_request) = get_proxy( )->create_resource_for_entity_set( c_entity
)->navigate_with_key( ls_key
)->create_request_for_delete(
).
lo_request->execute( ).
io_out->write( `Company deleted:` ).
ENDMETHOD.
ENDCLASS.
Fazit
Die Arbeit mit den Daten im Backend ist relativ einfach und folgt immer dem gleichen Schema. Im angelegten Consumption Modell bekommst du immer einige rudimentäre Beispiele, wie du die Abfragen Richtung On-Premise durchführen kannst oder du nutzt einfach unseren Artikel dafür.