4

How to perform a deep update with SAP Gateway OData V4 framework?

 1 year ago
source link: https://blogs.sap.com/2022/06/24/how-to-perform-a-deep-update-with-sap-gateway-odata-v4-framework/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
June 24, 2022 4 minute read

How to perform a deep update with SAP Gateway OData V4 framework?

Introduction

The SAP Gateway OData V4 framework does not support to perform a deep update.

This is also true for the OData V2 framework. And as a result also RAP based services do currently not support deep updates.

However today I learned about the need of such a support for an integration scenario where the consuming OData (or rather REST) client only supported updates using a payload which required a deep update support.

Since this support was only needed for a few API’s and since the requirement was not a generic support for deep updates I came to the conclusion (after some internal discussions) that a custom http handler would be an option in this case.

When checking the ICF node used by the SAP Gateway OData V4 framework we see that this uses the http handler class /IWBEP/CL_OD_ICF_HANDLER.

100_sicf.jpg

Custom http handler

For my POC I copied the class to a transportable class in the customer namespace and added a check in the code that checks

  1. if the incoming request is a PUT request and
  2. if the URL of the incoming request matches the URL of the entity that is to be updated

The copied http handler class ZIWBEP_CL_OD_ICF_HANDLER is registered in SICF for the OData V4 node.

100_sicf_changed.jpg

Method if_http_extension~handle_request

The important method is the method if_http_extension~handle_request.

In this method I have added a check for the http method that is used by the incoming request.

DATA(http_method_used) = to_lower( server->request->get_method( ) ).

IF lv_uri_path_after_handler_org = '/iwbep/v4_sample/default/iwbep/v4_gw_sample_basic/0001/salesorderlist(''0500000001'')' AND 
         http_method_used = 'put'.

If this check is not successful the standard implementation is called.

  METHOD if_http_extension~handle_request.
*    URL segments:
*      foo://example.com:8042/over/there?name=ferret
*      \_/   \______________/\_________/ \_________/
*       |           |            |            |
*    scheme     authority       path        query

    DATA:
      lo_request_handler            TYPE REF TO if_http_extension,
      "!" Path part of the URL behind the segment where the ICF handler (this class) is registered - AFTER alias resolution
      "! <br/>E.g. '/iwbep/tea/default/iwbep/tea_busi/0001/TEAMS'
      lv_uri_path_after_handler     TYPE string,
      "!" Path part of the URL behind the segment where the ICF handler (this class) is registered - BEFORE alias resolution
      lv_uri_path_after_handler_org TYPE string,
      "! Path part of the URL up to segment where the ICF handler (this class) is registered - AFTER alias resolution
      "! <br/>This must be '/sap/opu/odata4'
      lv_uri_path_up_to_handler     TYPE string.


    lv_uri_path_up_to_handler     = to_lower( server->request->get_header_field( if_http_header_fields_sap=>script_name_expanded ) ).
    lv_uri_path_after_handler     = to_lower( server->request->get_header_field( if_http_header_fields_sap=>path_info_expanded ) ).
    lv_uri_path_after_handler_org = to_lower( server->request->get_header_field( if_http_header_fields_sap=>path_info ) ).

    " This handler must only be registered under the ICF node '/sap/opu/odata4'
    ASSERT lv_uri_path_up_to_handler = /iwbep/cl_v4_url_util=>gc_icf_path_odata4.
    " An alias must not point behind an ICF node after node '/sap/opu/odata4'
    ASSERT lv_uri_path_after_handler = lv_uri_path_after_handler_org.
    DATA(http_method_used) = to_lower( server->request->get_method( ) ).


    IF lv_uri_path_after_handler_org = '/iwbep/v4_sample/default/iwbep/v4_gw_sample_basic/0001/salesorderlist(''0500000001'')' AND
           http_method_used = 'put'.

      DATA(payload) = server->request->get_cdata( ).
      "do something with payload

      server->response->set_cdata(
        EXPORTING
          data               = cl_demo_output=>get( 'Hello World' )
      ).
      server->response->set_status(
        EXPORTING
          code          = if_web_http_status=>ok
          reason        = 'success_deep_update'
      ).

    ELSE.



      IF lv_uri_path_after_handler = /iwbep/cl_v4_url_util=>gc_icf_path_async_monitor
      OR lv_uri_path_after_handler CP /iwbep/cl_v4_url_util=>gc_icf_path_async_monitor && '*'.
        lo_request_handler = NEW /iwbep/cl_od_http_req_hand_arm( ).

      ELSE.
        lo_request_handler = NEW /iwbep/cl_od_http_req_handler( ).

      ENDIF.

      lo_request_handler->handle_request( server ).
    ENDIF.
  ENDMETHOD.


  METHOD if_oauth2_consumer~provide_tadir_key_for_request.

    CONSTANTS:
      lc_program_id_r3tr           TYPE pgmid      VALUE 'R3TR',
      lc_object_type_service_group TYPE trobjtype  VALUE 'G4BA'.

    DATA:
      lv_uri_path_after_handler TYPE string,   " E.g. '/iwbep/tea/default/iwbep/tea_busi/0001/TEAMS'
      lv_service_group_id       TYPE /iwbep/v4_med_group_id.



    lv_uri_path_after_handler = i_http_request->get_header_field( if_http_header_fields_sap=>path_info_expanded ).
    /iwbep/cl_v4_url_util=>parse_path_after_handler(
      EXPORTING
        iv_uri = lv_uri_path_after_handler
      IMPORTING
        ev_service_group_id = lv_service_group_id ).

    e_tadir_key-obj_name = lv_service_group_id.
    e_tadir_key-object   = lc_object_type_service_group.
    e_tadir_key-pgmid    = lc_program_id_r3tr.

  ENDMETHOD.
ENDCLASS.

Result

When running a deep update request we can see in the debug mode that one is able to retrieve the payload of the request.

So it will be possible to parse the JSON file and to extract the data so that one can perform a custom implementation for the deep update.

200_payload_in_debug_mode.jpg

The result in the SAP Gateway Client then looks as follows:

300_result.jpg

As a reason “success_deep_update” is shown alongside with the response “Hello World” as it has been set in the coding of our custom http handler class.

server->response->set_cdata(
    EXPORTING
       data               = cl_demo_output=>get( 'Hello World' )
      ).
server->response->set_status(
    EXPORTING
          code          = if_web_http_status=>ok
          reason        = 'success_deep_update'
      ).

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK