Skip to Content
Author's profile photo Christian Jianelli

Building a CRUD Application with SAPUI5 and ICF REST/JSON Service – Part 2

This is the part 2 of 3 of this blog series. In this part we will see the implementation of the Create, Read, Update, Delete methods.

Click here if you did not read the Part 1.

Table of Contents

Part 1


Prerequisites

Overview

SAPLink Nuggets and Eclipse Project download

References

SAPUI5

SAPLink

SAPLink plugins (SCN Code Exchange)

CL_TREX_JSON_SERIALIZER bug fixes

Extending SAPUI5 JSON Model

Creating the ICF REST Service

Creating the custom handler class

Creating the ICF node

Retrieving the request method and the parameters passed in the URL

Part 2

Implementing the REST Service

Model and DDIC objects

Implementing the Create method (POST HTTP verb)

Implementing the Read method (HTTP GET verb)

Implementing the Update method (PUT HTTP verb)

Implementing the Delete method (DELETE HTTP verb)

Part 3

Creating the User Interface

Creating the project

Setting up the SAPUI5 bootstrap and required libraries

Creating the view components

Creating the BSPs to deploy the application and the SAPUI5 framework.

Implementing the Controller’s methods

Create

Read

Update

Delete

Find

Model and DDIC objects

To keep our code clean and adherent to the SoC (Separation of Concerns) principle, we will use a separated class to persist the changes in our contact list. To avoid deviating too much from the main subject, the creation of the model class and dictionary objects is not presented here. You can download here the nugg file with these objects.



Implementing the Create method (POST HTTP verb)

First of all we need to declare the necessary local types and variables.

METHOD if_http_extension~handle_request.

   TYPES: BEGIN OF local_type_response,

           success TYPE string,

           msg     TYPE string,

           data    TYPE ztt_scnblog2,

         END OF local_type_response.

* Objects

  DATA: lo_contact         TYPE REF TO zcl_scnblog2_contact,

        lo_json_serializer TYPE REF TO zcl_json_serializer. ” Copy of the standard class CL_TREX_JSON_SERIALIZER

* Internal tables

  DATA: lt_contacts TYPE STANDARD TABLE OF ztb_scnblog2.

* Structures

  DATA: ls_contact  TYPE ztb_scnblog2,

        ls_response TYPE local_type_response.

* Variables

  DATA: l_rc        TYPE i,

        l_json      TYPE string.

* Variables

  DATA: l_verb      TYPE string,

        l_path_info TYPE string,

        l_resource  TYPE string,

        l_param_1   TYPE string,

        l_param_2   TYPE string.

…..

Next we implement the code to handle the POST request method that corresponds to the Create Contact action.

WHEN ‘POST’.   ” C (Create)

     CLEAR: ls_contact,

             ls_response,

             l_rc.

*     Retrieve form data

      ls_contact-email     = server->request->get_form_field(’email’).

      ls_contact-firstname = server->request->get_form_field(‘firstname’).

      ls_contact-lastname  = server->request->get_form_field(‘lastname’).

*     Create an instance of the class to persist the Contact data in the database

      CREATE OBJECT lo_contact.

*     Create the Contact

      CALL METHOD lo_contact->create

        EXPORTING

          i_s_contact = ls_contact

        IMPORTING

          e_rc        = l_rc.

      IF l_rc IS INITIAL.

        ls_response-success = ‘true’.

        ls_response-msg     = ‘User created successfully!’.“hardcoded here intentionally

      ELSE.

        ls_response-success = ‘false’.

        ls_response-msg     = lo_contact->get_message( ).

      ENDIF.

*     Return the form data received back to the client

      APPEND ls_contact TO ls_response-data.

……

  ENDCASE.

  CREATE OBJECT lo_json_serializer

    EXPORTING

      DATA = ls_response. ” Data to be serialized

* Serialize ABAP data to JSON

  CALL METHOD lo_json_serializer->serialize.

* Get JSON string

  CALL METHOD lo_json_serializer->get_data

    RECEIVING

      rval = l_json.

* Sets the content type of the response 

  CALL METHOD server->response->set_header_field( name = ‘Content-Type’

    value = ‘application/json; charset=iso-8859-1’ ).

* Returns the results in JSON format 

  CALL METHOD server->response->set_cdata( data = l_json ).

ENDMETHOD.

Let’s understand what the above code does (only the relevant parts).

  • First we retrieve the form data received from the client application using the get_form_field method of the request object.

*     Retrieve form data

      ls_contact-email     = server->request->get_form_field(’email’).

      ls_contact-firstname = server->request->get_form_field(‘firstname’).

      ls_contact-lastname  = server->request->get_form_field(‘lastname’).


  • Next we create an instance of the class zcl_scnblog2_contact that will persist the Contact data in the database and call the create method.

*     Create an instance of the class to persist the Contact data in the database

      CREATE OBJECT lo_contact.

*     Create the Contact

      CALL METHOD lo_contact->create

        EXPORTING

          i_s_contact = ls_contact

        IMPORTING

          e_rc        = l_rc.

  • Next we need to handle the result of the action based on the return code (l_rc). Then we set the value of the attributes success and msg accordingly.

              IF l_rc IS INITIAL.

        ls_response-success = ‘true’.

        ls_response-msg     = ‘User created successfully!’.“hardcoded here intentionally

      ELSE.

        ls_response-success = ‘false’.

        ls_response-msg     = lo_contact->get_message( ).

      ENDIF.


  • The information received is returned back to the client application.

*     Return the form data received back to the client

      APPEND ls_contact TO ls_response-data. 

  • Finally the data is serialized in a JSON string.

  ENDCASE.

  CREATE OBJECT lo_json_serializer

    EXPORTING

      DATA = ls_response. ” Data to be serialized

* Serialize ABAP data to JSON

  CALL METHOD lo_json_serializer->serialize.

* Get JSON string

  CALL METHOD lo_json_serializer->get_data

      RECEIVING

        rval = l_json.

  • To send the JSON response to the client we need this last code.

* Sets the content type of the response   

  CALL METHOD server->response->set_header_field( name = ‘Content-Type’

    value = ‘application/json; charset=iso-8859-1’ ).

* Returns the results in JSON format 

  CALL METHOD server->response->set_cdata( data = l_json ).

ENDMETHOD.

Let’s test our first method using the Postman REST client.

Select the POST method and type the URL and the form fields. Be aware of using the correct field names (email, firstname, lastname).

scnblog2_023.JPG

Click the Send button to test the service. The service should return a JSON response with the message “Contact created successfully!”.

scnblog2_024.JPG

Let’s check the database table using the SE16.

scnblog2_025.JPG

If you hit the send button again without changing the form data the service should return a message informing that the contact already exist.

scnblog2_026.JPG

The created method is finished. Let’s go to the next method, read contact.

Implementing the Read method (HTTP GET verb)

Below is the code that we need to implement to handle the read method. It’s structure is very similar to the create method.

   WHEN ‘GET’.   ” R (Read)

      CLEAR: ls_contact,

             ls_response.

      CREATE OBJECT lo_contact.

*     Retrieve the Contact’s email passed in the URL

      ls_contact-email = l_param_1.

*     Retrieve querystring data

      ls_contact-firstname = server->request->get_form_field(‘firstname’).

      ls_contact-lastname  = server->request->get_form_field(‘lastname’).

*     Read Contact’s data

      CALL METHOD lo_contact->read

        EXPORTING

          i_s_contact  = ls_contact

        IMPORTING

          e_t_contacts = lt_contacts.

      IF NOT lt_contacts[] IS INITIAL.

        ls_response-success = ‘true’.

        ls_response-data[] = lt_contacts[].

      ELSE.

        ls_response-success = ‘false’.

        ls_response-msg     = lo_contact->get_message( ).

      ENDIF.

Let’s test our read method.

scnblog2_027.JPG

Implementing the Update method (PUT HTTP verb)

Below is the code that we need to implement to handle the update method.

   WHEN ‘PUT’. ” U (Update)

      CLEAR: ls_contact,

             ls_response,

             l_rc.

*     Retrieve the Contact’s email passed in the URL

      ls_contact-email = l_param_1.

*     Retrieve form data

      ls_contact-firstname = server->request->get_form_field(‘firstname’).

      ls_contact-lastname  = server->request->get_form_field(‘lastname’).

      CREATE OBJECT lo_contact.

*     Update the Contact

      CALL METHOD lo_contact->update

        EXPORTING

          i_s_contact = ls_contact

        IMPORTING

          e_rc        = l_rc.

      IF l_rc IS INITIAL.

        ls_response-success = ‘true’.

        ls_response-msg = ‘Contact updated successfully!’.  “Hardcoded here intentionally

      ELSE.

        ls_response-success = ‘false’.

        ls_response-msg     = lo_contact->get_message( ).

      ENDIF.

*     Return the form data received to the client

      APPEND ls_contact TO ls_response-data.

Let’s test our update method. Let’s put an “X” at the end of the contact’s first and last name.

scnblog2_028.JPG

Let’s check our table in the SE16.

scnblog2_029.JPG

Implementing the Delete method (DELETE HTTP verb)

Below is the code that we need to implement to handle the delete method.

WHEN ‘DELETE’. ” D (Delete)

      CLEAR: ls_contact,

             ls_response,

             l_rc.

      CREATE OBJECT lo_contact.

*     Retrieve the Contact’s email passed in the URL

      ls_contact-email = l_param_1.

*     Delete the Contact

      CALL METHOD lo_contact->delete

      EXPORTING

        i_s_contact = ls_contact

      IMPORTING

        e_rc        = l_rc.

      IF l_rc IS INITIAL.

        ls_response-success = ‘true’.

        ls_response-msg = ‘Contact deleted successfully!’.  “Hardcoded here intentionally

      ELSE.

        ls_response-success = ‘false’.

        ls_response-msg     = lo_contact->get_message( ).

      ENDIF.

Let’s test our delete method.


scnblog2_030.JPG

Now our table must be empty. Let’s check it in the SE16.

scnblog2_031.JPG

In the Part 3 of this blog series we will see the most interesting part, the creation of the user interface using SAPUI5.


Assigned Tags

      19 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Vidya Midavelil
      Vidya Midavelil

      Hi Christian,

      Great Post. I followed the instructions and tried to do a GET to retrieve some information, which am later trying to consume from SAPUI5 application via AJAX call.

      When I test the GET from Chrome Postman, I do not get the response data, just 'GET' alone.

      I placed a breakpoint at IF_HTTP_EXTENSION~HANDLE_REQUEST, and ran my UI5 app and I can see that it hits the breakpoint. I see that all data is passed correctly to the response from this method. However I get a error back instead of success after this call.

      Any idea how I can analyze and identify what is causing the error? Did you ever face similar issue?

      Thanks,

      Vidya

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi Janu,

      Thanks for your feedback.

      Please send me a screenshot of the error.

      Best regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Hi Christian,

      I am trying to upload NUGG_SCNBLOG2_ALL_OBJECTS.nugg file .

      its showing me following dump...plz help me.

      Short text
          Access via 'NULL' object reference not possible.

      What happened?
          Error in the ABAP Application Program

          The current ABAP program "ZSAPLINK_INSTALLER" had to be terminated because it
           has
          come across a statement that unfortunately cannot be executed.

      Error analysis
          An exception occurred that is explained in detail below.
          The exception, which is assigned to class 'CX_SY_REF_IS_INITIAL', was not
           caught in
          procedure "GETSTRUCTUREFROMATTRIBUTES" "(METHOD)", nor was it propagated by a
           RAISING clause.
          Since the caller of the procedure could not have anticipated that the
          exception would occur, the current program is terminated.
          The reason for the exception is:
          You attempted to use a 'NULL' object reference (points to 'nothing')
          access a component.
          An object reference must point to an object (an instance of a class)
          before it can be used to access components.
          Either the reference was never set or it was set to 'NULL' using the
          CLEAR statement.

      Missing RAISING Clause in Interface
          Program                                 ZSAPLINK_INSTALLER
          Include                                 ZSAPLINK_INSTALLER
          Row                                     833
          Module type                             (METHOD)
          Module Name                             GETSTRUCTUREFROMATTRIBUTES

      Thanks & Regards,

      Praphull

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi Praphull,

      You have to use the ZSAPLINK report, not the ZSAPLINK_INSTALLER.

      Best Regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Hi Christian,

      Thnks for helpful reply...

      I have one more doubt..in part3..I have created 'zscnblog2' BSP sucessfully..imported index.html & web content from eclipse worlplace.

      but for ZSAPUI5 BSP which index page i need to copy(same of zscnblog2) & which SAPUI5 files do i need to import.

      as of now in the demo documnt i didnt see any project named SAPUI5(in eclipse.)

      Please help me...

      Regards,

      Praphull

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi,

      For the ZSAPUI5 BSP you have to upload the files that are in the sapui5-static.zip.

      If you unzip this file you will find the index.html in the root folder.

      Best regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Very useful and detail blog post. Thanks much for your time Christian!

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi Nguyen,

      Thanks for your feedback!

      Best regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Hi Christian,

      Looks great so far.  One problem though, in the put, get and delete calls I don't see you filling l_param_1.  Therefore all of my corresponding non-push calls are failing.  Did I miss something?

      Thanks,

      Joe

      Author's profile photo Former Member
      Former Member

      Never mind.  I see where it is filled.  For some reason in my system this returned a null value:

      l_path_info = server->request->get_header_field( name = '~path_info' ).

      To get around this I had to do the following:

         l_query_string = server->request->get_header_field( name = '~query_string' ).

         split l_query_string at '&' into table lt_parameters.

         loop at lt_parameters into ls_parameter.

           split ls_parameter at '=' into l_para_id

                                          l_para_value.

           if l_para_id = 'email'.

             exit.

           endif.

         endloop.


      Then I set  ls_contact-email = l_para_value instead of l_param_1 for example.  This works.

      Thanks,

      Joe

      Author's profile photo Former Member
      Former Member

      Hi Christian,


      Very nice blog. but i am facing problem in the POSTmethod. I have used same code for the post method which you have posted above but i am not able receive data through json format. If i call post method through Postman REST client by passing json in raw tab and in json format i am not able to receive but whereas if use form-data and pass as you mentioned in the below screenshot i am able to receive the data.

      sample json format: {"email":"abc@gmail.com","firstname":"abc","lastname":"xyz"}


      Thanks in advance. scnblog2_023.JPG

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi Siddeshwara,

      Thanks for you feedback.

      The REST service implemented for this blog works only with form-data submission. In order to work with raw data submission you will have to retrieve the json data sent as raw data by calling the method GET_CDATA of the request object. After that, you will have parse the json data so you can use it.

      Regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Thanks a lot...Its working now. one more help.

      I am able to deserialize one json array.Eg: it_data[{"email":"abc@gmail.com"}] but if i am having two array like {it_data[{"email":"abc@gmail.com"}],it_output[{"name":"abc"}]} i am not able to parse it. I will be able to parse only dividing json string into two array and then parse it.

      Is there any other way to parse it if i am having multiple array in json string.

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Hi Siddesh,

      I suggest you to use zJSON to parse it.

      se38/zJSON · GitHub

      (usage examples)

      Usage zJSON · se38/zJSON Wiki · GitHub

      Regards,

      Christian

      Author's profile photo Former Member
      Former Member

      Thank you very much 🙂

      Author's profile photo Former Member
      Former Member

      Hi Christian,

      I am not able to call my SICF service in SAP UI5 ajax call. please find below code.

      //ajax call

      $.ajax({

            url: 'http://.../sap/bc/test_sui5',

              type: 'GET',

              contentType : "application/json",

              dataType: 'json',

              username:'abc',

              password:'abc123',        

              timeout: 10000,

              cache: false,

              success: function(data, textStatus, xhr) {

                  alert("success");

                  alert(textStatus);

             },

              error: function(xhr, textStatus, errorThrown) {

                  alert("error");

                  alert(textStatus);

              }

          });

      please help me to resolve this issue.

      Note: I am calling ICF Service directly in SAP UI5 Ajax call.

      Regards,

      Sid

      Author's profile photo Vadim Zaripov
      Vadim Zaripov

      For all having Malformed JSON as the result.

      Don't use the standard CL_TREX_JSON_SERIALIZER. Copy it to ZCL_TREX_JSON_SERIALIZER and change according to the following blog post:Serialize ABAP data into JSON format

      Author's profile photo Christian Jianelli
      Christian Jianelli
      Blog Post Author

      Yes, as described in the part 1 of this blog post in the Prerequisites section (last item).

      Thanks,

      Christian Jianelli

      Author's profile photo Vadim Zaripov
      Vadim Zaripov

      Yeah, I guess my note is for someone like me, who thought that in 2015 in NW 7.4 SAP has patched the standard CL_TREX_JSON_SERIALIZER to serialize JSON correctly 🙂