Monday 17 October 2022

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.

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Jobs, SAP ABAP Guides, SAP ABAP Tutorial and Materials, SAP ABAP BTP, SAP ABAP Guides
Workflow Instance

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

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Jobs, SAP ABAP Guides, SAP ABAP Tutorial and Materials, SAP ABAP BTP, SAP ABAP Guides
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 .

SAP ABAP Certification, SAP ABAP Career, SAP ABAP Skills, SAP ABAP Jobs, SAP ABAP Guides, SAP ABAP Tutorial and Materials, SAP ABAP BTP, SAP ABAP Guides
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.

No comments:

Post a Comment