Skip to Content
Author's profile photo Andre Fischer

OData service development with SAP Gateway using CDS via Referenced Data Sources – How to implement updates

Introduction

 

The OData service that has been generated in the first part of this blog is read only.

 

In the second part of the blog OData service development with SAP Gateway using CDS via Referenced Data Sources I would like to show how we can make the description of the sales order updatable.

 

This will show

 

  1. how simple updates can be implemented and in particular
  2. how this can be done for Texts that are accessed by the SADL framework via a join and the annotation @ObjectModel.text.association: ‘_Text’.

In another blog I also showed how eTags can be handled for this service and how you can even add a function import

How to handle etags in SAP Gateway using code based implementation

 

Change history

  • 17.06.2016 – Fixed a typo that the DEFINE method is located in the DPC_EXT class rather than in the MPC_EXT class
  • 24.11.2016 – Moved code samples to code boxes to avoid problems with cut and paste
  • 05.05.2017 – Added information how to handle etags for updates and how to implement a function import

 

 

Service Implementation

 

  • Open the Service Builder project ZE2E100_<XX>_2 again that has been built based on the blog mentioned above.
  • Expand the folder Runtime artifacts and right-click on ZZCL_ZE2E100_XX_2_DPC_EXT and choose the entry Go To ABAP Workbench.

/wp-content/uploads/2016/06/image098_966129.png

  • Switch to edit mode, scroll down to the method ZSEPM_C_SALESORD_UPDATE_ENTITY and make sure to select it and click on the Redefine Method button.

/wp-content/uploads/2016/06/rds_cud_01_966372.jpg

  • Copy and Paste the coding into the Update method

 

 

 

 

  method zsepm_c_salesord_update_entity.

    data: lt_keys               type /iwbep/t_mgw_tech_pairs,
          ls_key                type /iwbep/s_mgw_tech_pair,
          ls_so_id              type bapi_epm_so_id,
          ls_headerdata_update  type bapi_epm_so_header,
          ls_headerdatax        type bapi_epm_so_headerx,
          ls_headerdata_key     type zcl_ze2e100_xx_2_mpc=>ts_zsepm_c_salesorder_tpltype,
          ls_headerdata_payload type zcl_ze2e100_xx_2_mpc=>ts_zsepm_c_salesorder_tpltype,
          lt_return             type table of bapiret2,
          ls_return             type          bapiret2,
          err_msg               type          string,
          ls_message            type          scx_t100key.

    call method io_tech_request_context->get_converted_keys
      importing
        es_key_values = ls_headerdata_key.

    io_data_provider->read_entry_data( importing es_data =  ls_headerdata_payload ).

    ls_so_id-so_id = ls_headerdata_key-salesorder.

    " Product header data (non-key) fields that can be updated
    " via the BAPI are marked with an 'X'

    ls_headerdatax-so_id = ls_headerdata_key-salesorder.
    ls_headerdatax-note = 'X'.

    " move content of the fields that should be
    " updated from payload to the corresponding
    " field of the BAPI

    move ls_headerdata_key-salesorder to ls_headerdata_update-so_id.
    move ls_headerdata_payload-t_salesorder  to ls_headerdata_update-note.

    call function 'BAPI_EPM_SO_CHANGE'
      exporting
        so_id         = ls_so_id         " EPM: SO Id
        soheaderdata  = ls_headerdata_update " EPM: so header data of BOR object
        soheaderdatax = ls_headerdatax
      tables
        return        = lt_return.     " Return Parameter

    if lt_return is not initial.

      loop at lt_return into ls_return.
        err_msg = ls_return-message .
      endloop.

      ls_message-msgid = 'SY'.
      ls_message-msgno = '002'.
      ls_message-attr1 = err_msg.

      raise exception type /iwbep/cx_mgw_busi_exception
        exporting
          textid = ls_message.

    endif.
  endmethod.

 

Info: The replaced coding above retrieves the content of the properties of the incoming request.

Since different DDIC structures are used by the entity type and the BAPI that is used to update the sales order the incoming fields are moved to the data structure used by the BAPI.

 

  • To make the SAP Web IDE CUD Master Detail Template aware that the property SalesOrder_Text is now updatatable we have to annotate the property using the annoation sap:updatable=true.In this special case this cannot be done in the CDS view. So we have to use the option to add additional metadata by implementing the DEFINE method in the model provider extension class.
  • Expand the folder Runtime artifacts and right-click on ZZCL_ZE2E100_XX_2_MPC_EXT and choose the entry Go To ABAP Workbench.
  • Copy and paste the following coding into the DEFINE method.

 

  method define.

    data:
      lo_entity_type type ref to /iwbep/if_mgw_odata_entity_typ,
      lo_property    type ref to /iwbep/if_mgw_odata_property.

    call method super->define( ).
    lo_entity_type = model->get_entity_type( iv_entity_name = 'Zsepm_C_Salesorder_TplType').
    lo_property = lo_entity_type->get_property( iv_property_name = 'SalesOrder_Text').
    lo_property->set_updatable( abap_true ).

  endmethod.

 

     l

  • Click on Activate.
  • Confirm the activation popup.

 

Since the update method is now implemented you can now test your service. This can be done by the built in REST client, the SAP Gateway Client which I can really recommend.

 

After you have tested the service successfully using the SAP Gateway Client you can use SAP Web IDE to generate an application based on the Master Detail CUD template.

 

Test the service using the SAP Gateway Client

 

  • Navigate back to the Service Builder by pressing the “Back-Button” several times
  • In the navigation tree right-click on GW_HUB and select SAP Gateway Client.Alternatively start the SAP Gateway Client in a separate window by starting transaction /n/IWFND/GW_CLIENTIf we now test the update using the SAP Gateway Client this should work fine.

 

  • Enter the following URI/sap/opu/odata/SAP/ZE2E100_XX_2_SRV/Zsepm_C_Salesorder_Tpl(‘5000000<XX>’)After pressing Execute button you see a single sales order.Replace ‘<XX>’ with your group name
  • Press the Use as Request button to create a proper http request body.
    Change the content of the field SalesOrder_Text for example to ‘Test Update Text’.
    Change the http method from GET to PUT.
    Press Execute

/wp-content/uploads/2016/06/rds_cud_03_966381.jpg

  • As a result you get an empty http response with the return code 204.

/wp-content/uploads/2016/06/rds_cud_04_966380.jpg

  • Now again perform a GET request to verify that the data has been changed
    Enter the following URI
    /sap/opu/odata/SAP/ZE2E100_XX_2_SRV/Zsepm_C_Salesorder_Tpl(‘5000000<XX>’)
    After pressing Execute button you see a single sales order with the changed text.
    Replace ‘<XX>’ with your group name

/wp-content/uploads/2016/06/rds_cud_04a_966442.jpg

 

Testing the service with SAP Web IDE

When creating an application based on the CRUD-Q Master Detail template you will be able to build an application that allows you to update sales orders as shown in the following screen shot.

 

/wp-content/uploads/2016/06/rds_cud_05_966343.jpg

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Vinayshree S
      Vinayshree S

      Can we also implement Update using funtion imports, if so.. which is better method?

      Author's profile photo Andre Fischer
      Andre Fischer
      Blog Post Author

      You can do so. Function imports should however only be used if the update cannot be performed via an update on an entity set.

      example could be the approval of a Sales Order.

      Regards,

      Andre

      Author's profile photo Daniel Emmenegger
      Daniel Emmenegger

      Hi Andre
      Thanks for this example. Unfortunately I've always the following error, when updating the text. This occurs also, when I test the FunctionModule in SE37.

      Any ideas?
      SEPM_BOR_MESSAGES    006 EPM problem: Changing the note of Sales Order 0500000000 has failed

      Regards,
      Daniel

      Author's profile photo Former Member
      Former Member

      @Daniel: First I had the same problem, when I tried to change the field “Note” of the Sales Order Header.

      Then I tried to change it by using the following function module and it worked:

      FUNCTION Z_BAPI_EPM_SO_ITEM_CHANGE.
      *”———————————————————————-
      *”*”Local Interface:
      *”  IMPORTING
      *”     VALUE(SO_ID) TYPE  SNWD_SO_ID OPTIONAL
      *”     VALUE(SO_ITEM_POS) TYPE  SNWD_SO_ITEM_POS OPTIONAL
      *”  EXPORTING
      *”     VALUE(ITEMDATA) TYPE  BAPI_EPM_SO_ITEM
      *”  TABLES
      *”      RETURN STRUCTURE  BAPIRET2
      *”———————————————————————-
      DATA:
      it_soitemdata  TYPE STANDARD TABLE OF BAPI_EPM_SO_ITEM, “tables param
      wa_soitemdata   LIKE LINE OF it_soitemdata,
      it_soitemdatax TYPE STANDARD TABLE OF BAPI_EPM_SO_ITEMX, “tables param
      wa_soitemdatax LIKE LINE OF it_soitemdatax,
      it_return       TYPE STANDARD TABLE OF BAPIRET2, “tables param
      wa_return       LIKE LINE OF it_return,
      ls_return       LIKE LINE OF it_return.
      
      data: ls_so_header            type bapi_epm_so_header,
      ls_so_headerx           type bapi_epm_so_headerx,
      lt_error_info           type bapirettab,
      ls_so_id                type bapi_epm_so_id.
      
      DATA(ld_so_id) = ‘Check type of data required’.
      DATA(ld_soheaderdata) = ‘Check type of data required’.
      DATA(ld_soheaderdatax) = ‘Check type of data required’.
      DATA(ld_persist_to_db) = ‘Check type of data required’.
      
      “populate fields of struture and append to itab
      append wa_soitemdata to it_soitemdata.
      
      “populate fields of struture and append to itab
      append wa_soitemdatax to it_soitemdatax.
      
      “populate fields of structure and append to itab
      append wa_return to it_return..
      
      ” modify all BAPI header data fields that are allowed to be updated
      ” and specify the corresponding BAPI header modification info
      ls_so_id = ‘0500000000’.
      ls_so_header–so_id         = ‘0500000000’.
      ls_so_header–currency_code = ‘USD’.
      ls_so_header–note          = ‘This note will be updated’.
      ”    ls_so_header-buyer_id      = go_test_data->ms_bp_510-bp_id.
      
      ls_so_headerx–so_id         = ls_so_id.
      ls_so_headerx–currency_code = abap_true.
      ls_so_headerx–note          = abap_true.
      ”    ls_so_headerx-buyer_id      = abap_true.
      
      call function ‘BAPI_EPM_SO_CHANGE’
      exporting
      so_id         = ls_so_id
      soheaderdata  = ls_so_header
      soheaderdatax = ls_so_headerx
      tables
      return        = return.
      
      IF SY–SUBRC EQ 0.
      “All OK
      ENDIF.
      ENDFUNCTION.
      
      

      On the SAP system I was working on the BAPI “BAPI_EPM_SO_CHANGE” only allowed some fields of the sales order header data to be changed: “Note” and “Currency_Code”.

      In the SAP Gateway Service Builder I created the mapping for the Update Method of the SalesOrderHeaderSet (EntitySet) like in the following picture: