Implementing Reading Operations

Objectives

After completing this lesson, you will be able to:
  • Implement a query operation
  • Implement a read operation

Implementation of a Query Operation

Development flow: Service implementation

The service model was created by importing a DDIC structure in the SAP Gateway project and the runtime artifacts were generated. The next step is to provide source code to handle OData requests. This can be done in the following ways:

Implement ABAP-Code
You redefine and implement the respective methods of the data provider extension class (DPC_EXT) in the ABAP Workbench or ABAP Development Tools.
Code Mapping
You establish a relationship between the interface parameters of a reuse unit and the properties of an entity set using the built-in mapping tool of the SAP Gateway Service Builder.

We skip the code mapping for now and focus on implementing the ABAP-code.

Development steps: Method implementation and test

Implementing the methods in the DPC_EXT means overwriting the corresponding methods from the DPC. The most frequently redefined methods are as follows:

  • <Entity Set>_CREATE_ENTITY – creates the resource corresponding to a specified entity type
  • <Entity Set>_DELETE_ENTITY – deletes a resource of a specified entity type
  • <Entity Set>_GET_ENTITY – retrieves an entity of a specified entity type
  • <Entity Set>_GET_ENTITYSET – retrieves a collection of a specified entity type
  • <Entity Set>_UPDATE_ENTITY – changes a resource for a specified entity type

These methods are listed in the SAP Gateway project under Service Implementation for each entity set. The context menu entry Go to ABAP Implementation forwards you directly in the selected method implementation.

Screenshot flow about redefining the GetEntitySet (Query)

If the method is not yet implemented in the DPC_EXT, an information popup informs you about that and the Continue button opens the DPC_EXT itself in the ABAP Workbench. There you can redefine the method as usual.

In our example, we want to implement the query operation for all products. The PRODUCTSET_GET_ENTITYSET method can be opened following the path Service ImplementationProductSetGetEntitySet (Query)Got to ABAP Workbench. It is not yet implemented. So we select it in the navigation area and choose Redefine.

Caution

A common error is to double-click the method in the ABAP Workbench instead of choosing Redefine. Although a popup states that this double-click opens the method implementation of the superclass, many beginners just start to implement this method. But any code implemented in the superclass – the data provider base class – will just be overwritten by the next generation of runtime artifacts. (You do this error only once.)
Source code implementing a query operation

For an <Entity Set>_GET_ENTITYSET method, the export parameter et_entityset should be filled with the data requested by the OData request. The parameter is typed using a tt_<Entity Type> table type generated in the MPC based on the definition of the entity type in the data model.

It is recommended to call a reuse unit for reading the requested data instead of implementing any SQL statement in this method. In that way, there is a clear separation of service implementation and database operation. In this example, the BAPI_EPM_PRODUCT_GET_LIST is called to get all products from the database.

Errors should be raised by using the exception classes /IWBEP/CX_MGW_BUSI_EXCEPTION for errors in the business logic, while technical exceptions should be raised via /IWBEP/CX_MGW_TECH_EXCEPTION. For example, checks should be implemented if an entity set is marked as non-addressable.

The exception classes offer several parameters to provide more details about the error. For example, the message_container parameter allows to collect multiple messages in one object. The mo_context attribute of the DPC provides such a message container, which can be filled using several methods like add_message_from_bapi() awaiting the return parameter of a BAPI.

Finally, CORRESPONDING or MOVE-CORRESPONDING is used to pass the result to the SAP Gateway framework. This is useful if not all fields of the structure provided by the reuse unit have been used for the entity set. In addition, the implementation would also work if the underlying structure is enhanced by an append structure.

The following block provides the example source code in a copy-friendly way:

Code Snippet
1234567891011121314151617181920212223
METHOD productset_get_entityset. DATA: lt_headerdata TYPE TABLE OF bapi_epm_product_header, lt_return TYPE TABLE OF bapiret2. * Get data CALL FUNCTION 'BAPI_EPM_PRODUCT_GET_LIST' TABLES headerdata = lt_headerdata return = lt_return. IF lt_return IS NOT INITIAL. " Message Container mo_context->get_message_container( ) ->add_messages_from_bapi( lt_return ). RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = /iwbep/cx_mgw_busi_exception=>business_error message_container = mo_context->get_message_container( ). ENDIF. * Fill response data et_entityset = CORRESPONDING #( lt_headerdata ). ENDMETHOD.

Implementation of a Read Operation

Screenshot flow about redefining GetEntity (Read)

To implement the read operation for one product, we follow the same pattern as for the query operation. The PRODUCTSET_GET_ENTITY method can be opened following the path Service ImplementationProductSetGetEntity (Read)Got to ABAP Workbench. It is not yet implemented. So we select it in the navigation area and choose Redefine.

Source code implementing a read operation

For an <Entity Set>_GET_ENTITY method, the export parameter er_entity should be filled with the data requested by the OData request. The parameter is typed using a ts_<Entity Type> structure generated in the MPC based on the definition of the entity type in the data model.

The io_tech_request_context parameter provides the OData request header and can be found in every CRUD or query method. It is typed based on an interface suitable for the individual method it is part of. For a read operation, the /IWBEP/IF_MGW_REQ_ENTITY interface provides methods to get request data like the key of the requested resource. Its get_converted_keys() method returns a structure that has the same type as the entity but only the key fields are filled. So there is no need to loop over a list of key fields.

In this example, the BAPI_EPM_PRODUCT_GET_DETAIL is called to get the product using the provided key from the database.

Errors should be raised by using the exception classes /IWBEP/CX_MGW_BUSI_EXCEPTION for errors in the business logic, while technical exceptions should be raised via /IWBEP/CX_MGW_TECH_EXCEPTION. The add_message_from_bapi() method of the message container is again used to pass the errors of the BAPI to the exception.

Finally, CORRESPONDING is used to pass the result to the SAP Gateway framework.

The following block provides the example source code in a copy-friendly way:

Code Snippet
1234567891011121314151617181920212223242526272829303132333435
METHOD productset_get_entity. DATA: ls_product_id TYPE bapi_epm_product_id, ls_headerdata TYPE bapi_epm_product_header, lt_return TYPE TABLE OF bapiret2. * Get key fields from request io_tech_request_context->get_converted_keys( IMPORTING es_key_values = er_entity ). * Map key fields to function module parameters ls_product_id-product_id = er_entity-product_id. * Get data CALL FUNCTION 'BAPI_EPM_PRODUCT_GET_DETAIL' EXPORTING product_id = ls_product_id IMPORTING headerdata = ls_headerdata TABLES return = lt_return. IF lt_return IS NOT INITIAL. " Message Container mo_context->get_message_container( ) ->add_messages_from_bapi( lt_return ). RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = /iwbep/cx_mgw_busi_exception=>business_error message_container = mo_context->get_message_container( ). ENDIF. * Fill response data er_entity = CORRESPONDING #( ls_headerdata ). ENDMETHOD.

Implement a Read Operation

Business Example

You are a developer or solution architect in your company. You need to perform a basic implementation of the method for reading a single entity.

Template:
GW100_S_QUERY (SAP Gateway Project)
Solution:
GW100_S_READ (SAP Gateway Project)

Note

This exercise requires an SAP Learning system. Login information are provided by your system setup guide.

Note

You may continue with your solution of the previous exercise or copy the template to ZGW100_##_QUERY. Whenever the values or object names in this exercise include ##, replace ## with the number of your user.

Prerequisites

The data model was defined and the service was registered in exercise Define a Data Model Based on a Data Dictionary Structure.

Task 1: Implement a Read Operation using SAP Gateway Service Builder

Steps

  1. In the SAP Gateway Service Builder of your SAP S/4HANA (S4H) system, navigate to the implementation of the PRODUCTSET_GET_ENTITY method of your project.

    1. In the SAP Easy Access of your S4H, search for SAP Gateway Service Builder or start transaction SEGW.

    2. In the SAP Gateway Service Builder for your project, expand Service ImplementationProductSet.

    3. In the context menu of GetEntity (Read), choose Go to ABAP Workbench.

    4. In the Information popup, choose Continue.

      Result

      The method is not yet implemented.
  2. In the Class Builder, redefine the method PRODUCTSET_GET_ENTITY to read a single product by calling the BAPI_EPM_PRODUCT_GET_DETAIL function module.

    1. In the Class Builder, choose Display <-> Change.

    2. Place the curser into the method PRODUCTSET_GET_ENTITY and choose Redefine.

    3. Write the following code or copy it from the solution:

      Code Snippet
      123456789101112131415161718192021222324252627282930313233343536
      METHOD productset_get_entity. DATA: ls_product_id TYPE bapi_epm_product_id, ls_headerdata TYPE bapi_epm_product_header, lt_return TYPE TABLE OF bapiret2. * Get key fields from request io_tech_request_context->get_converted_keys( IMPORTING es_key_values = er_entity ). * Map key fields to function module parameters ls_product_id-product_id = er_entity-product_id. * Get data CALL FUNCTION 'BAPI_EPM_PRODUCT_GET_DETAIL' EXPORTING product_id = ls_product_id IMPORTING headerdata = ls_headerdata TABLES return = lt_return. IF lt_return IS NOT INITIAL. " Message Container mo_context->get_message_container( ) ->add_messages_from_bapi( lt_return ). RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING textid = /iwbep/cx_mgw_busi_exception=>business_error message_container = mo_context->get_message_container( ). ENDIF. * Fill response data er_entity = CORRESPONDING #( ls_headerdata ). ENDMETHOD.
    4. Choose Activate.

    5. In the Inactive Objects popup, select all objects and choose Continue.

    6. Choose Exit.

Task 2: Test the Read Operation using SAP Gateway Client

Steps

  1. In the SAP Gateway Client of your S4H, test the read operation in your service. Read a single product.

    1. In the SAP Gateway Service Builder of your S4H, double-click Service Maintenance.

    2. Choose SAP Gateway Client.

    3. In the SAP Gateway Client, select HTTPS as Protocol.

    4. Choose Entity Set.

    5. In the Entity Sets popup, double-click ProductSet.

      Example

      /sap/opu/odata/SAP/ZGW100_##_STUDENT_SRV/ProductSet
    6. Choose Execute.

      Result

      The HTTP Response displays the products.
    7. In the Request URI field, add the key of a product to the URI.

      Example

      /sap/opu/odata/SAP/ZGW100_##_STUDENT_SRV/ProductSet('HT-1000')
    8. Choose Execute.

      Result

      The HTTP Response displays the product.
  2. Test the query option $select in your service. Select the product ID, name, and category of a single product.

    1. In the Request URI field, add ?$select=ProductId,Name,Category to the URI.

      Example

      /sap/opu/odata/SAP/ZGW100_##_STUDENT_SRV/ProductSet('HT-1000')?$select=ProductId,Name,Category
    2. Choose Execute.

      Result

      The HTTP Response displays the product id, name, and category of the product.
  3. Test the query option $value in your service. Read only the name of a product.

    1. In the Request URI field, replace ?$select=ProductId,Name,Category with /Name/$value.

      Example

      /sap/opu/odata/SAP/ZGW100_##_STUDENT_SRV/ProductSet('HT-1000')/Name/$value
    2. Choose Execute.

      Result

      The HTTP Response displays only the name of the product.