Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
k_sood
Active Participant
 

In this Blog, I would like to present some code snippets, which could help others in order to consume Token based REST APIs in ABAP.

 

Obtaining the relevant details in order to get the Token

In order to get the Token, details like Application ID, Application Secret, Client ID and the Token Endpoint must be provided by the Provider.

Example how these details looks like is as follows:


Application ID, Client ID and Secret are simply data strings and the Token Endpoint is a URL.

Code Snippet in order to get a Token

The definition of which header parameters are needed in order to successfully call the Token Endpoint has to be provided by the API Provider.
METHOD get_token.
DATA: lo_http_token TYPE REF TO if_http_client,
l_response_token TYPE string.
DATA: l_status_code TYPE i.
DATA: lv_bas64enc TYPE string.
DATA: lv_url_token TYPE string,
lv_client_id TYPE string.
DATA: lo_root TYPE REF TO cx_root.

TRY.
*Url to access token
lv_url_token = IS_API_CREDENTI-token_endpoint. "Token Endpoint

* create http client Object
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_url_token
IMPORTING
client = lo_http_token
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*Close the client in case of Error
lo_http_token->close( ).
ENDIF.

* Set Method POST
IF lo_http_token IS BOUND.
lo_http_token->request->set_method( if_http_entity=>co_request_method_post ).
ENDIF.

*Set header parameter
*Convert string to base64
CONCATENATE IS_API_CREDENTI-APPLICATION_ID ':' IS_API_CREDENTI-APPLICATION_SEC INTO lv_bas64enc .



cl_http_utility=>encode_base64( EXPORTING
unencoded = lv_bas64enc
RECEIVING
encoded = lv_bas64enc ).

CONCATENATE 'Basic ' lv_bas64enc INTO lv_bas64enc RESPECTING BLANKS.

lo_http_token->request->set_header_field(
EXPORTING
name = 'Authorization'
value = lv_bas64enc
).

lo_http_token->request->set_header_field(
EXPORTING
name = 'Content-Type'
value = 'application/x-www-form-urlencoded'
).
lo_http_token->request->set_header_field(
EXPORTING
name = 'Accept'
value = 'application/json'
).
*Set all the form parameters
lo_http_token->request->set_form_field(
EXPORTING
name = 'grant_type'
value = 'client_credentials'
).

lo_http_token->request->set_form_field(
EXPORTING
name = 'scope'
value = 'client'
).


lv_client_id = IS_API_CREDENTI-client_id.
lo_http_token->request->set_form_field(
EXPORTING
name = 'client_id'
value = lv_client_id
).

* Turn off logon popup. detect authentication errors.
lo_http_token->propertytype_logon_popup = 0.

* Send / Receive Token Request
CALL METHOD lo_http_token->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

CALL METHOD lo_http_token->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

CALL METHOD lo_http_token->response->get_status
IMPORTING
code = l_status_code.

*Json response needs to be converted to abap readable format
CALL METHOD lo_http_token->response->get_cdata
RECEIVING
data = l_response_token.


/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_token
CHANGING
data = is_token "Token will be stored in the instance structure, for retrieval in other methods.
).

lo_http_token->close( ).
CATCH cx_root INTO lo_root.
ENDTRY.
ENDMETHOD.

Data is_token is of the following type
    BEGIN OF ts_token,
token_type TYPE string,
access_token TYPE string,
expires_in TYPE string,
END OF ts_token .

 

Calling an API with PUT operation using the Obtained token including Error Handling

In the following code, An API is called using the Token obtained above in order to write some data on the API Provider side. Various return status codes which could come as return have also been processed.

Details of the Parameters which needs to be provided in order to make a call has to come from the API provider, Also the details about the structure of the error data has to come from the API provider.
METHOD put_employee_call.
DATA: lv_url_api TYPE string.
DATA: lo_http_put_empl TYPE REF TO if_http_client.

DATA: lo_root TYPE REF TO cx_root.

DATA: lv_access_token TYPE string.
DATA: l_response_put TYPE string.

DATA: l_status_code TYPE i.
DATA: ls_mitarbeiter_put_resp_422 TYPE ts_put_resp_unprocessable,
ls_mitarbeiter_put_resp_400_4 TYPE ts_put_resp_400_4.

DATA: ls_errors_422 TYPE ts_put_errors,
ls_msg TYPE bal_s_msg,
lv_text TYPE char200,
ls_emp_put_resp_200_201 TYPE ts_put.

TRY.


lv_url_api = is_api_credenti-api_endpoint_new .

*Create http client Object
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_url_api
IMPORTING
client = lo_http_put_empl
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*Close the client in case of Error
lo_http_put_empl->close( ).
ENDIF.
*Set Method POST
IF lo_http_put_empl IS BOUND.
lo_http_put_empl->request->set_method( 'PUT' ).
ENDIF.

*Set Header fields
lo_http_put_empl->request->set_header_field(
EXPORTING
name = 'Accept'
value = 'application/json'
).

lo_http_put_empl->request->set_header_field(
EXPORTING
name = 'Content-Type'
value = 'application/json'
).

CONCATENATE is_token-token_type is_token-access_token INTO lv_access_token SEPARATED BY space.

lo_http_put_empl->request->set_header_field(
EXPORTING
name = 'Authorization'
value = lv_access_token
).
*Set body Parameter
lo_http_put_empl->request->append_cdata( data = iv_empl_json ).
* Turn off logon popup. detect authentication errors.
lo_http_put_empl->propertytype_logon_popup = 0.

*Send / Receive PUT Request
CALL METHOD lo_http_put_empl->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

CALL METHOD lo_http_put_empl->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

*Get status code
CALL METHOD lo_http_put_empl->response->get_status
IMPORTING
code = l_status_code.

*Obtain Json response
CALL METHOD lo_http_put_empl->response->get_cdata
RECEIVING
data = l_response_put.

*deserializing json response
CASE l_status_code.
WHEN '422' . " Unprocessable Entry
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_mitarbeiter_put_resp_422
).
*Add log for every Error Entry
LOOP AT ls_mitarbeiter_put_resp_422-errors INTO ls_errors_422.
CONCATENATE ls_errors_422-field ls_errors_422-code ls_errors_422-message INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'E'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,ls_errors_422,lv_text.
ENDLOOP.

WHEN '400' OR '404'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_mitarbeiter_put_resp_400_4
).
*Add one log Entry for 400 or 404
CONCATENATE ls_mitarbeiter_put_resp_400_4-message ls_mitarbeiter_put_resp_400_4-code INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'E'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.

*Add one Success entry for Update
WHEN '200'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_emp_put_resp_200_201
).

CONCATENATE ls_emp_put_resp_200_201-external_id TEXT-002 INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'S'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.

*Add one Success entry for Creation
WHEN '201'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_emp_put_resp_200_201
).
CONCATENATE ls_emp_put_resp_200_201-external_id TEXT-003 INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'S'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.
ENDCASE.
lo_http_put_empl->close( ).
CATCH cx_root INTO lo_root.
ENDTRY.
ENDMETHOD.

 

Thanks

Ketan

 

 
14 Comments
Labels in this area