Matinal: Analysis of the whole process of SAP ABAP publishing HTTP RestFul service (5)

1. Background introduction

RESTful is a design style and development method for web applications. REST is the abbreviation of Representational State Transfer, and the Chinese translation is “representational state transfer”. It may not be easy to understand REST from the definition alone. For students who have just come into contact with this concept, REST can be understood as a design style, which describes an architectural style network system, such as a web application.

SAP supports ABAP language to build RESTful applications. Using the ABAP RESTful programming model, you can quickly develop SAP Fiori applications or web service interfaces.
2. Principle and structure

SAP’s ABAP RESTful Programming Model provides a standard architecture that makes it very easy to develop end-to-end applications and is naturally RESTful. Its architecture diagram is as follows:

This architecture contains 3 layers:

* Data Modeling & Behavior: Data Model & Behavior layer; in this layer, the three tasks of “CDS data modeling”, “model behavior definition” and “behavior implementation” are mainly completed.

– Data modeling based on CDS (Core Data Services) will not be explained too much here. CDS is a powerful tool to take advantage of the high performance of HANA;

– Behavior Definition, referred to as BDEF, is completed using BDL (Behavior Definition Language) to support various operations of the business model, such as CREATE, UPDATE, DETETE and other behaviors. Behavior definition mainly serves this application. Various transaction operations.

– The implementation logic of various “behaviors” is implemented through ABAP code, that is, various corresponding methods in the corresponding ABAP Class are implemented, such as CREATE, UPDATE, DETETE, etc.

* Business Service Provisioning: Business service preparation layer; this layer mainly completes the definition and implementation of various “services”.

– Service Definition: Service definition, that is, the mapping of the data model in the previous step, what data and behaviors need to be exposed in the form of “service”.

– Service Binding: In service binding, the implementation of the specific “protocol” will be completed and the service type provided to the consumer will be determined. (A Service Definition can have one or more Service Bindings).

* Service Consumption: Service consumption layer; in this layer, various exposed services are provided to Fiori or other front-end applications in the form of OData for use.
3. Build model & publish service

The implementation of Core Data Services (CDS) in the data modeling layer is based on the underlying database table. The CDS layer can use and directly operate the original data in the database table;

In the service preparation layer, fields related to the foreground application can be further exposed through CDS Project View. In Projection View, UI annotations can be used to control the display mode of specific fields in the foreground UI.

Through Service Definition, you can further define which data will be exposed as a Business Service.

Through Service Binding, a defined service can be bound to a CS (Client-Server) architecture communication protocol, such as the well-known OData. At the same time, you can use Service Binding to complete the preview of SAP Fiori Element, and see the specific effects of the application in the preview.

So far, we have introduced the process from underlying DB table modeling to service publishing. Through the above steps, we can complete the development of a read-only application (data display and query functions can be completed through this App).

4. Definition and reinforcement of behavior

If the application needs to have richer behaviors in addition to display and query, we can achieve this by defining “Behavior” and implementing “Action & Validation”.

Behavior Definition can further define operations such as creation, update, and deletion of data (CREATE, UPDATE, DELETE); in Behavior implementation, specific creation, update, and deletion logic can be further completed through ABAP code (in this step, the relevant creation , update and delete ABAP code will be automatically generated, we only need to simply define the declaration of the implementation class, which is very convenient).

In addition to basic functions such as “add, delete, modify, and query” of data, there may also be requirements for “validity verification of data” in actual business. For this requirement, you can add the “Validation” of the instance. For more complex business logic, you can further implement it by adding “Action”. For example, after clicking a button in the front-end UI, perform an operation and other similar requirements.

5. Summary

As you can see, SAP provides a very convenient ABAP RESTful programming framework. Based on this framework, developers can easily create SAP Fiori applications or other web services without knowing the specific underlying technical details. This is also Let developers have more time to focus on business logic. This technology trend is more in line with the actual needs of enterprises.

SAP’s ABAP RESTful programming framework is not only suitable for on-premise scenarios, it is also suitable for development on SAP Cloud Platform. Therefore, it is very convenient for ABAPer to use ABAP RESTful to quickly build and publish applications on the Cloud.

There are many implementation methods on the Internet through the IF_HTTP_EXTENSION interface. The method used this time is different.
The specific process is as follows:
1. Code process

Create a class ZLOCAL_CL_REST using SE24 and inherit the super class CL_REST_HTTP_HANDLER.

2. Reconstruction method IF_REST_APPLICATION~GET_ROOT_HANDLER, HANDLE_CSRF_TOKEN, where HANDLE_CSRF_TOKEN is used for token verification. If token verification is not required, it can be refactored directly. No code is required. If verification is required, the verification logic can be written under this method.

3. Refactored code, where /GET/PO is the interface path and ZLOCAL_CL_GET_PURCHASEORDER is the interface class

4.TOKEN verification. If verification is required, the method can be reconstructed: HANDLE_CSRF_TOKEN. Under the original code logic, when using the GET method, the token can be obtained correctly by logging in with the Authentication account and password when sending the request. If you don’t need a token, just refactor it directly, no code is required.
5. After the above is completed, use SE24 again to create a class named the previous interface class ZLOCAL_CL_GET_PURCHASEORDER. And inherit the super class CL_REST_RESOURCE.

6. After inheritance, reconstruct the corresponding methods according to the different calling methods of the interface.

Here we use GET method for demonstration

 METHOD if_rest_resource~get.
*CALL METHOD SUPER->IF_REST_RESOURCE~GET
* .
    DATA: lv_output_json TYPE string.
    DATA: lv_ebeln TYPE ebeln.
    DATA: BEGIN OF ls_out,
            ebeln TYPE ebeln,
            bukrs TYPE bukrs,
            bsart TYPE bsart,
            aedat TYPE aedat,
            ernam TYPE ernam,
            lifnr TYPE lifnr,
            ekorg TYPE ekorg,
          END OF ls_out.
    DATA: BEGIN OF ls_output,
            code TYPE char3,
            clnt TYPE sy-mandt,
            status TYPE char10,
            content TYPE string,
            data LIKE ls_out,
          END OF ls_output.
    DATA(rt_parameters) = mo_request->get_uri_query_parameters()."Get parameters"
    LOOP AT rt_parameters ASSIGNING FIELD-SYMBOL(<fs_par>).
      TRANSLATE <fs_par>-name TO UPPER CASE.
      TRANSLATE <fs_par>-value TO UPPER CASE.
    ENDLOOP.
    ls_output-clnt = sy-mandt.
    READ TABLE rt_parameters INTO DATA(ls_par) WITH KEY name = 'EBELN'.
    IF sy-subrc IS INITIAL AND ls_par-value IS NOT INITIAL.
      CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
        EXPORTING
          input = ls_par-value
        IMPORTING
          output = lv_ebeln.
      SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_out FROM ekko
        WHERE ebeln = lv_ebeln.
      IF sy-subrc IS INITIAL.
        ls_output-data = ls_out.
        ls_output-code = cl_rest_status_code=>gc_success_ok.
        ls_output-status = 'success'.
        ls_output-content = 'Get successful'.
      ELSE.
        ls_output-data = ls_out.
        ls_output-code = cl_rest_status_code=>gc_success_ok.
        ls_output-status = 'fail'.
        ls_output-content = 'Getting failed'.
      ENDIF.
    ELSE.
      ls_output-data = ls_out.
      ls_output-code = cl_rest_status_code=>gc_redirection_permanent.
      ls_output-status = 'fail'.
      ls_output-content = 'Parameter error'.
    ENDIF.

    /ui2/cl_json=>serialize(
   EXPORTING
     data = ls_output
     compress = abap_false
     pretty_name = /ui2/cl_json=>pretty_mode-camel_case
   RECEIVING
     r_json = lv_output_json ).
     
    "Response content"
    mo_response->create_entity( )->set_string_data( lv_output_json ).
    "Response content type: application/json"
    mo_response->create_entity( )->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
    "Response status: Not required"
    mo_response->set_status( cl_rest_status_code=>gc_success_ok ).
    "Response description: optional"
    mo_response->set_reason( cl_rest_status_code=>get_reason_phrase( cl_rest_status_code=>gc_success_ok ) ).
  ENDMETHOD.

Get the body via POST.

 "POST parameters, JSON"
    DATA(lv_input_json) = io_entity->get_string_data(

2. Use SICF configuration service

The configuration is as follows, the processor is ZLOCAL_CL_REST, which is the class created for the first time.

3. Postman test

1. Call correctly

2. If the path is incorrect, it will prompt that there are no suitable resources.

3. The method is not enabled and prompts that it is not supported.

4. Use token

To use token, you need to call it in POST mode. First, refactor the methods IF_REST_RESOURCE~POST in class ZLOCAL_CL_GET_PURCHASEORDER. For testing, we simply refactored it here.

METHOD if_rest_resource~post.
  TYPES:BEGIN OF ts_indata,
          matnr TYPE matnr,
          maktx TYPE maktx,
        END OF ts_indata.
  DATA: ls_data TYPE ts_indata.
  TYPES: BEGIN OF ts_outdata,
           code TYPE char3.
      INCLUDE TYPE ts_indata.
  TYPES:
        END OF ts_outdata.
  DATA: ls_outdata TYPE ts_outdata.
  "POST method to pass in parameters, JSON"
  DATA(lv_input_json) = io_entity->get_string_data( ).

  "Convert JSON to internal table"
  /ui2/cl_json=>deserialize(
    EXPORTING
      json = lv_input_json
    CHANGING
        data = ls_data ).

  CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
    EXPORTING
      input = ls_data-matnr
    IMPORTING
      output = ls_data-matnr
    EXCEPTIONS
      length_error = 1
      OTHERS = 2.

  SELECT SINGLE maktx FROM makt INTO ls_data-maktx WHERE matnr = ls_data-matnr.

  "Internal table conversion to JSON"
  DATA: lv_output_json TYPE string.

  MOVE-CORRESPONDING ls_data TO ls_outdata.

  ls_outdata-code = cl_rest_status_code=>gc_success_ok .

  /ui2/cl_json=>serialize(
     EXPORTING
       data = ls_outdata
       compress = abap_false
       pretty_name = /ui2/cl_json=>pretty_mode-camel_case
     RECEIVING
       r_json = lv_output_json ).

  "Response content"
  mo_response->create_entity( )->set_string_data( lv_output_json ).
  "Response status: Not required"
  mo_response->set_status( cl_rest_status_code=>gc_success_ok ).
  "Response description: optional"
  mo_response->set_reason( cl_rest_status_code=>get_reason_phrase( cl_rest_status_code=>gc_success_ok ) ).
ENDMETHOD.

2. Add the Basic Authentication account password to the request, otherwise it cannot be obtained.

3. Use Postman to obtain token
Add the x-csrf-token parameter to the headers of the request, with the value fetch, to obtain the token value in the headers of the response.

4. Test token
1. Using the wrong token will prompt verification failure.

2. Correct token