Cancel BTP workflow instance from ABAP

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%20Instance

Workflow Instance

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

Service%20Key%20Credentials

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%20Workflow%20Instance

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