Writing a SICF service
Introduction
This blog will guide you through the process of creating a SICF service (REST). SICF is an SAP transaction which is used to maintain services for HTTP communication, using the Internet Communication Manager (ICM) and the Internet Communication Framework (ICF). This can be useful in multiple situations. For example: A certain system might not have the proper Gateway installation or configuration to create services there.
Following steps will be taken to create and test such a service:
- Creating a structure and table type
- Creating the ZIF_REST Interface.
- Creating a Handler Class
- Creating the class for a GET Request
- Creating the class for a POST Request
- Creating a node in transaction SICF
- Testing the GET service
- Testing the POST service
1. Creating a structure and table type
Let’s create a structure for the entries we want to get later on.
Create a table type for that structure.
2. Creating the ZIF_REST Interface.
To start off with, let’s create an interface in ‘SE24’ (if it doesn’t exist yet) which we will use for almost all classes in this guide. The interface consists of two methods, one for the request and one for the response.
Add the attributes ‘RESPONSE‘ and ‘REQUEST‘ to the interface.
The method ‘SET_RESPONSE’ has an importing parameter ‘IS_DATA’ with the ‘XSTRING’ type. Make sure you activate the interface.
3. Creating a Handler Class
Go to ‘SE24’ and create a new class called ‘ZCL_REST_TEST‘. Select the tab ‘Interfaces’ and add interface ‘IF_HTTP_EXTENSION’.
Go back to the tab ‘Methods’ and you’ll see a method has been added. Add another method called ‘GET_REST’.
Add the following parameters to the method ‘GET_REST’.
Copy the following code to your method ‘IF_HTTP_EXTENSION~HANDLE_REQUEST’.
It will execute the ‘GET_REST’ method to get the class we want to execute to get or process the data.
METHOD IF_HTTP_EXTENSION~HANDLE_REQUEST. *************************************************************************** " VARIABLES *************************************************************************** DATA: LO_REST_CLASS TYPE REF TO ZIF_REST. DATA: LO_ERROR TYPE REF TO CX_ROOT. DATA: LV_REASON TYPE STRING. *************************************************************************** " GET THE CLASS OBJECT *************************************************************************** TRY. LO_REST_CLASS ?= GET_REST( IO_SERVER = SERVER ). *************************************************************************** " EXECUTE THE RETRIEVED CLASS *************************************************************************** LO_REST_CLASS->HANDLE_REQUEST( ). *************************************************************************** " ERROR *************************************************************************** CATCH CX_ROOT INTO LO_ERROR. LV_REASON = LO_ERROR->GET_TEXT( ). SERVER->RESPONSE->SET_STATUS( CODE = 500 REASON = LV_REASON ). ENDTRY. ENDMETHOD.
This method will first check what type of request we’re dealing with (GET, PUT, POST, … etc.). It will then append the name to the base class name. So, if a GET request is executed, the name of the class it will execute is ‘ZCL_REST_TEST_GET’.
METHOD GET_REST. *************************************************************************** " VARIABLES *************************************************************************** DATA: LV_CLASS_NAME TYPE SEOCLSNAME. DATA: LV_REQUEST_METHOD TYPE STRING. *************************************************************************** " APPEND REQUEST METHOD TO BASE CLASS *************************************************************************** LV_REQUEST_METHOD = IO_SERVER->REQUEST->GET_HEADER_FIELD( '~request_method' ). CONCATENATE 'ZCL_REST_TEST_' LV_REQUEST_METHOD INTO LV_CLASS_NAME. *************************************************************************** " RETURN CLASS OBJECT *************************************************************************** TRY. CREATE OBJECT EO_REST TYPE (LV_CLASS_NAME) EXPORTING IO_REQUEST = IO_SERVER->REQUEST IO_RESPONSE = IO_SERVER->RESPONSE. *************************************************************************** " ERRORS *************************************************************************** CATCH CX_SY_CREATE_OBJECT_ERROR. ENDTRY. ENDMETHOD.
4. Creating the class for a GET Request
Go to ‘SE24’ and create a new class ‘ZCL_REST_TEST_GET’ and add interface ‘ZIF_REST’.
Your class will now have the first two methods below. Add two new methods: ‘GET_EQUIPMENTS’ and ‘CONSTRUCTOR’.
Add the following parameters to ‘GET_EQUIPMENTS’. This will pass the request and return the equipments we will retrieve.
Add the following parameters to ‘CONSTRUCTOR’. This will instantiate the class when called upon.
Open method ‘HANDLE_REQUEST’. This method will be executed from the handler class (‘ZCL_REST_TEST’).
It will first get the equipments which will be converted to a JSON String. The String will then be added as output of this method.
METHOD ZIF_REST~HANDLE_REQUEST. *************************************************************************** " VARIABLES *************************************************************************** DATA: LT_EQUIPS TYPE ZTT_TEST_EQUI. DATA: LV_STRING_WRITER TYPE REF TO CL_SXML_STRING_WRITER. DATA: LV_XSTRING TYPE XSTRING. *************************************************************************** " EXECUTE GET_EQUIPMENTS METHOD *************************************************************************** TRY. LT_EQUIPS = GET_EQUIPMENTS( ME->ZIF_REST~REQUEST ). *************************************************************************** " CONVERT EQUIPMENTS TO JSON *************************************************************************** LV_STRING_WRITER = CL_SXML_STRING_WRITER=>CREATE( TYPE = IF_SXML=>CO_XT_JSON ). CALL TRANSFORMATION ID SOURCE ARRAY = LT_EQUIPS RESULT XML LV_STRING_WRITER. LV_XSTRING = LV_STRING_WRITER->GET_OUTPUT( ). *************************************************************************** " ADD THE JSON EQUIPMENTS TO THE RESPONSE *************************************************************************** ME->ZIF_REST~RESPONSE->SET_DATA( DATA = LV_XSTRING ). CATCH CX_ROOT. ENDTRY. ENDMETHOD.
Now open method ‘SET_RESPONSE’ and add following code. This method will be executed when ‘HANDLE_REQUEST’ has finished. It will return the data as a String.
METHOD ZIF_REST~SET_RESPONSE. CALL METHOD ME->ZIF_REST~RESPONSE->SET_DATA EXPORTING DATA = IS_DATA. ENDMETHOD.
Now open method ‘CONSTRUCTOR’ and add following code. This method will instantiate the request and response when the class is called.
METHOD CONSTRUCTOR. ME->ZIF_REST~RESPONSE = IO_RESPONSE. ME->ZIF_REST~REQUEST = IO_REQUEST. ENDMETHOD.
Now open method ‘GET_EQUIPMENTS’. This method will select an equipment which number is equals to the header parameter.
METHOD GET_EQUIPMENTS. *************************************************************************** " VARIABLES *************************************************************************** DATA: LV_EQUI_NUMBER TYPE EQUNR. *************************************************************************** " GET HEADER PARAMETERS VALUE FROM URL *************************************************************************** LV_EQUI_NUMBER = ME->ZIF_REST~REQUEST->GET_FORM_FIELD('equnr'). UNPACK LV_EQUI_NUMBER TO LV_EQUI_NUMBER. *************************************************************************** " GET EQUIPMENTS SELECT *************************************************************************** SELECT EQUI~EQUNR, EQKT~EQKTX FROM EQUI AS EQUI LEFT OUTER JOIN EQKT AS EQKT ON EQKT~EQUNR EQ EQUI~EQUNR INTO TABLE @ET_EQUIPMENTS WHERE EQUI~EQUNR EQ @LV_EQUI_NUMBER AND EQKT~SPRAS EQ 'E'. ENDMETHOD.
5. Creating the class for a POST Request
Go to ‘SE24’ and create a new class ‘ZCL_REST_TEST_POST’ and add interface ‘ZIF_REST’.
Your class will now have the first two methods below. Add a new method: ‘CONSTRUCTOR’.
Add the following parameters to ‘CONSTRUCTOR’. This will instantiate the class when called upon.
Open method ‘HANDLE_REQUEST’. This method will be executed from the handler class (‘ZCL_REST_TEST’). It will use the data that was added as the body of the POST request. Add the data as JSON.
METHOD ZIF_REST~HANDLE_REQUEST. *************************************************************************** " TYPES *************************************************************************** TYPES: BEGIN OF TYPE_EQUI, EQUNR TYPE STRING, EQKTX TYPE STRING, END OF TYPE_EQUI. *************************************************************************** " VARIABLES AND OBJECTS *************************************************************************** DATA: LS_EQUI TYPE TYPE_EQUI. DATA: LT_EQUIS TYPE TABLE OF TYPE_EQUI. DATA: LR_DESERIALIZER TYPE REF TO CL_TREX_JSON_DESERIALIZER. DATA: LV_JSON_BODY TYPE STRING. DATA: LV_STRING_WRITER TYPE REF TO CL_SXML_STRING_WRITER. DATA: LV_XSTRING TYPE XSTRING. CREATE OBJECT LR_DESERIALIZER. *************************************************************************** " JSON TO ABAP DATA *************************************************************************** LV_JSON_BODY = ME->ZIF_REST~REQUEST->GET_CDATA( ). LR_JSON_DESERIALIZER->DESERIALIZE( EXPORTING JSON = LV_JSON_BODY IMPORTING ABAP = LS_EQUI ). APPEND LS_EQUI TO LT_EQUIS. *************************************************************************** " CREATE OBJECT *************************************************************************** "DO WHATEVER YOU NEED TO DO HERE WITH THE DATA !!! *************************************************************************** " CONVERT INPUT TO JSON STRING *************************************************************************** LV_STRING_WRITER = CL_SXML_STRING_WRITER=>CREATE( TYPE = IF_SXML=>CO_XT_JSON ). CALL TRANSFORMATION ID SOURCE ARRAY = LT_EQUIS RESULT XML LV_STRING_WRITER. LV_XSTRING = LV_STRING_WRITER->GET_OUTPUT( ). *************************************************************************** " RETURN CREATED OBJECT AS RESPONSE (CONVENTION) *************************************************************************** ME->ZIF_REST~RESPONSE->SET_DATA( DATA = LV_XSTRING ). ENDMETHOD.
Now open method ‘SET_RESPONSE’ and add following code. This method will be executed when ‘HANDLE_REQUEST’ has finished. It will return the data as a String.
METHOD ZIF_REST~SET_RESPONSE. CALL METHOD ME->ZIF_REST~RESPONSE->SET_DATA EXPORTING DATA = IS_DATA. ENDMETHOD.
Now open method ‘CONSTRUCTOR’ and add following code. This method will instantiate the request and response when the class is called.
METHOD CONSTRUCTOR. ME->ZIF_REST~RESPONSE = IO_RESPONSE. ME->ZIF_REST~REQUEST = IO_REQUEST. ENDMETHOD.
6. Creating a node in transaction SICF
Go to transaction ‘SICF’ and find a fitting node to which we can append a new one. In this case, we’ll opt for the already existing ‘ZREST’ node. Right click the node and add a new sub-element. We’ll name this node .
Add a fittting description for the service node.
Navigate to the ‘Hander List’ tab and add the handler we created (‘ZCL_REST_TEST’).
Make sure you save the service properly.
Go back to the node list and right click the node you created and click ‘Activate service’.
Click one of the two following buttons to active the node/service.
7. Testing the GET service
Open Postman or something else to test web services. Add the correct URL and authorization and press ‘SEND’.
This will return an array with data. In this case only the equipment where the equipment number matches.
8. Testing the POST service
Open Postman or something else to test web services. Add the correct URL and authorizations.
Add the JSON body to the request and press ‘SEND’.
You’ll get the posted object as result.
That’s all there is to it. Thank you for reading and if there is any feedback or comments at all, you should definitely let me know since this is the first blog I’ve ever written.
More information in: