Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
sujitsingh5191
Explorer
Introduction:

As an abapper most of us might be new to calling external APIs from the ABAP environment. There are lots of APIs on cloud foundry or deployed elsewhere which we can use as per as our need. Most of them use the OAuth 2.0 authentication and other authentication processes.

You must have heard about SAP Workflow Management Triggering the workflow and getting in my In Box. But What about cancelling the running workflow instance from the ABAP environment.

In this blog we not only learn how to cancel the workflow instance but also we can use this to call any APIs which uses OAuth 2.0 authentication.

Scenario:

Let's imagine a scenario where I triggered a workflow for some PR amount. But I need to change the PR amount and retrigger new workflow with the new amount, also cancelling the previous workflow instance, so the users are in sync with the new approval amount. In this case there are APIs that are available and documented on the Cloud Foundry.

The workflow API is documented and available in the API hub Workflow API for Cloud Foundry

The prerequisites for calling the API are:

  1. Workflow Instance Id.

  2. Client Id, Client Secret, URL of workflow service instance for generating Bearer token

  3. Workflow API of cloud foundry to update the status of the workflow instance.


 

Below in the workflow instance created for workflow service in service marketplace and your workflow must be bound to this instance.


Workflow Instance


 

Use the credentials of the service key of the above workflow instance.


Service Key Credentials


 

Client Id, Secret and URL are used to generate the Bearer token required for OAuth 2.0 authentication.

 

Now we are all set to call the workflow Api from the Abap environment.

 

Code:

Below is the code for your reference.
    DATA : lv_body          TYPE string,
lv_client_id TYPE string,
lv_client_secret TYPE string.

DATA: lv_service TYPE string.
DATA: lv_json_data TYPE string,
lr_data TYPE REF TO data,
lv_token TYPE string,
lv_token_type TYPE string,
lv_body_data TYPE string,
ls_ex_sum_hdr TYPE zicam_exec_sum,
lv_wfid TYPE string,
lv_url TYPE string.

FIELD-SYMBOLS: <data> TYPE data,
<results> TYPE any,
<table> TYPE any,
<structure> TYPE any,
<field> TYPE any,
<field_value> TYPE data.

"store client Id, secret and Url, workflow instance Id in some table for different environments and fetch at runtime.

CALL METHOD call_token_service(
EXPORTING
iv_client_id = lv_client_id
iv_client_secret = lv_client_secret
iv_url = lv_url
IMPORTING
ev_token = lv_token
ev_token_type = lv_token_type ).

lv_wf_id = ''. "Fetch from some table where you store the active worflow instance

lv_service = 'https://api.workflow-sap.cfapps.us20.hana.ondemand.com/workflow-service/rest/v1/workflow-instances/' && lv_wf_id .

lv_body_data = lv_body = |\{"status": "CANCELED","cascade": false \}| .

DATA: lo_http_client TYPE REF TO if_http_client.

CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_service
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.

IF sy-subrc <> 0.
"error handling
ENDIF.

"setting request method
lo_http_client->request->set_method('PATCH').

CONCATENATE 'Bearer' lv_token INTO DATA(lv_auth_value) SEPARATED BY space.
"adding headers
lo_http_client->request->set_header_field( name = 'Authorization' value = lv_auth_value ) ##NO_TEXT.
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ) ##NO_TEXT.
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ) ##NO_TEXT.


CALL METHOD lo_http_client->request->set_cdata
EXPORTING
data = lv_body_data.

CALL METHOD lo_http_client->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.

IF sy-subrc = 0.
CALL METHOD lo_http_client->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 5.
ENDIF.

IF sy-subrc <> 0.
"error handling
ENDIF.
lo_http_client->response->get_status(
IMPORTING
code = DATA(lv_code) ).
IF lv_code <> 202.
lv_json_data = lo_http_client->response->get_cdata( ).
ev_error = 'X'.
ENDIF.




METHOD call_token_service.


DATA: lv_service TYPE string.
DATA: lv_json_data TYPE string,
lr_data TYPE REF TO data.

FIELD-SYMBOLS: <data> TYPE data,
<results> TYPE any,
<table> TYPE ANY TABLE,
<structure> TYPE any,
<field> TYPE any,
<field_value> TYPE data.

lv_service = iv_url && '/oauth/token'.

DATA: lo_http_client TYPE REF TO if_http_client.

cl_http_client=>create_by_url(
EXPORTING
url = lv_service
IMPORTING
client = lo_http_client
EXCEPTIONS ##SUBRC_OK
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
).

lo_http_client->request->set_method( 'POST' ).

lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/x-www-form-urlencoded' ) ##NO_TEXT.
DATA : lv_data TYPE string.
DATA : lv_client_id TYPE string.
DATA : lv_client_secret TYPE string.

lv_client_id = iv_client_id.


lv_client_secret = iv_client_secret.

lv_data = |grant_type=client_credentials&client_id={ lv_client_id }&client_secret={ lv_client_secret }|.
CALL METHOD lo_http_client->request->set_cdata
EXPORTING
data = lv_data.

CALL METHOD lo_http_client->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.

IF sy-subrc = 0.
CALL METHOD lo_http_client->receive
EXCEPTIONS ##SUBRC_OK
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 5.
ENDIF.


lo_http_client->response->get_status(
IMPORTING
code = DATA(lv_code) ).
IF lv_code = 200.
TYPES : BEGIN OF ty_token,
access_token TYPE string,
token_type TYPE string,
expires_in TYPE i,
scope TYPE string,
END OF ty_token.

DATA : ls_token TYPE ty_token.
lv_json_data = lo_http_client->response->get_cdata( ).
cl_fdt_json=>json_to_data( EXPORTING iv_json = lv_json_data
CHANGING ca_data = ls_token ).
IF ls_token IS NOT INITIAL .
ev_token = ls_token-access_token.
ev_token_type = ls_token-token_type.
ENDIF.
ENDIF.

ENDMETHOD.

 

Initially the token generation method where I have used the client Id, secret and URL to generate the bearer token. The bearer token is used to call the workflow service on cloud to cancel the workflow instance.

Conclusion:

You can see the workflow instance on the cloud is cancelled .



Cancelled Workflow Instance


 

Now you should be able to call any external APIs which uses the OAuth 2.0 authentication following the API documentation using the above steps.

I hope this blog will help you in calling many more APIs on cloud foundry.

 

Please feel free to share feedback or thoughts in a comment below .

Also do follow my profile to get more technical information on SAP BTP and similar content .

 

This related post can also help you to call external Restful service.

Call external Restful service from ABAP
5 Comments
Labels in this area