BTP - Access methods On-Premise (OData)
In this article we look at the other access methods to an OData service via the proxy classes.
Table of contents
In the last article, we looked at how we make an OData service available in the ABAP environment and how we call it for the first time. In addition to fetching data, there are other scenarios for working with the API in the backend, which we want to take a closer look at in this article.
Introduction
As already mentioned in the last article, we have to create a proxy class before access, which we can use to create our proxy object in order to be able to access the backend. In this case, we use a destination from the Destination Service again and create the object in a separate method GET_PROXY. We use this method in all of the following examples:
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 with filter
The last time we accessed it, we had read all the data from the interface. In this example, we want to apply a filter to a field so that only a subset of the data is read. In the first step we create a range with the appropriate filters and then create an object for reading. We then create a filter factory and set up a filter for access.
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 ).
The entries found in LT_FOUND are now returned from the backend, these correspond to our applied filter:
CREATE
In the second example we want to create a new data set on-premise. To do this, we define a structure with the new values, but the key of the entity must at least be filled. Then we create an object for the system and transfer the data. At the end we execute the request via Execute.
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 ).
If we look at the table in the data preview, the new data set has been created. With another read query, we could then determine the data:
UPDATE
In this step, we now want to update the previously created data record and give it a description. To do this, we define two structures, one for the key and one with the data. Before we can create the update object, we need to navigate through the key. When updating, we set the HTTP method to PUT. Finally, we transfer the new data again and execute the request.
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 this case, the data is now complete via the data preview and we see the filled description in the backend system:
DELETE
Finally, we want to remove the record from the system. In this case we only need the key structure, navigate through it and create an object for deletion. In the end, executing the query is enough and the data record is deleted.
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` ).
Full example
Here is the complete sample class again with the execution. In order for this to work, an existing destination must be added and the API must run in the target system:
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.
Conclusion
Working with the data in the backend is relatively easy and always follows the same pattern. In the created consumption model you always get some rudimentary examples of how to carry out the queries towards on-premises or you simply use our article for it.