How to consume RESTful Enterprise Messaging in ABAP

Int4 Team
2020-04-28

In this blog post you will learn:

  • How to configure connection to Enterprise Messaging from your ABAP system
  • How to send and consume messages from the service

Introduction

In this article I will show you how to connect from your on-premise system to the Enterprise Messaging service and how to process messages from ABAP via the REST protocol. We will also take a look at the management APIs. Let’s go!

Prerequisites:

  1. You have already created an Enterprise Messaging service instance on your Cloud Foundry trial account. If not, take a look at this documentation:

Destinations in SM59

We will need to create three  destinations in SM59. You could actually handle it manually in the code but it’s much more convenient to have it all in our beloved transaction – it means less code to write in the future plus all options are easily maintainable.

We will create a destination for obtaining token for further communication, management destination for getting information about our service and finally messaging destination for sending and consuming messages.

Go to your space (dev in my case) and go to your Enterprise Messaging service instance (sandbox in my case):

SAP Cloud Platform Cockpit

On the next screen go to Service Keys. If you haven’t created one yet – do this now. You will use it to bind and authorize connections. From the service key we will need to get three pieces of information.

Token Destination

When you look at the service key you will see two sections – messaging and management. There is only one authorization credential and endpoint for token, so it doesn’t matter which section you will take it from.

Token Destination

Create a destination in SM59:

SM59 Destination creation

In the path prefix use ‘/oauth/token?grant_type=client_credentials&response_type=token’. In the Logon & Security use the Basic Authentication. Use ‘clientid’ as user and ‘clientsecret’ as password from the service key. Set SSL Active and use SSL Client (Standard). Follow this documentation to configure your SSL:

Management destination

Create management destination in SM59:

Management Destionation creation2

In the host use the uri from management section in your service key. No Logon & Security settings are necessary here as authentication will be performed with the use of the token.

Messaging destination

Now move to ‘messaging’ section in your service key and create the messaging destination with the REST uri.

Management destination SM59

Enterprise Messaging

In this case no Logon & security is necessary.

Let’s code a little bit

We went through the most confusing part, now we can move on and have some fun. Let’s create the HTTP and the REST client:

cl_http_client=>create_by_destination(

       EXPORTING

           destination              = 'ENTERPRISE_MESSAGING_AH_TOKEN'

       IMPORTING

           client                   = DATA(lo_http_client_token)

       EXCEPTIONS

           argument_not_found       = 1

           destination_not_found    = 2

           destination_no_authority = 3

           plugin_not_active        = 4

           internal_error           = 5

           OTHERS                   = 6

   ).

    IF sy-subrc <> 0.

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    ENDIF.




DATA(lo_rest_client_token) = NEW cl_rest_http_client( lo_http_client_token ).

Do the same for all three destinations.

Now let’s fetch the token.

TYPES: BEGIN OF ty_token,

             access_token TYPE string,

             token_type   TYPE string,

             expires_in   TYPE string,

           END OF ty_token.




DATA: ls_token             TYPE ty_token.




lo_rest_client_token->if_rest_client~post( lo_rest_client_token ->if_rest_client~create_request_entity( ) ).




    DATA(lv_response) = lo_rest_client_token ->if_rest_client~get_response_entity( )->get_string_data( ).




    /ui2/cl_json=>deserialize(

      EXPORTING

        json             = lv_response

      CHANGING

        data             = ls_token

    ).

TYPES: BEGIN OF ty_token,

             access_token TYPE string,

             token_type   TYPE string,

             expires_in   TYPE string,

           END OF ty_token.




DATA: ls_token             TYPE ty_token.




lo_rest_client_token->if_rest_client~post( lo_rest_client_token ->if_rest_client~create_request_entity( ) ).




    DATA(lv_response) = lo_rest_client_token ->if_rest_client~get_response_entity( )->get_string_data( ).




    /ui2/cl_json=>deserialize(

      EXPORTING

        json             = lv_response

      CHANGING

        data             = ls_token

    ).

Class /ui2/cl_json will help us with transforming JSON responses into ABAP structures. Remember that our token can expire (in EE it’s around a few hours, so it’s not a threat in our case). If you wanted to handle that anyway, I do it this way:

GET TIME STAMP FIELD DATA(lv_timestamp).




lv_token_expiry_time = cl_abap_tstmp=>add( EXPORTING tstmp   = lv_timestamp

                                                     secs    = CONV #( ls_token-expires_in ) ).
GET TIME STAMP FIELD DATA(lv_timestamp).




DATA(lv_valid) = COND abap_bool( WHEN lv_timestamp >= lv_token_expiry_time THEN abap_false

                       ELSE abap_true ).

And later you can check:

GET TIME STAMP FIELD DATA(lv_timestamp).

DATA(lv_valid) = COND abap_bool( WHEN lv_timestamp >= lv_token_expiry_time THEN abap_false
ELSE abap_true ).

When you have your token you are ready to go!

Let’s post a message to a queue in the Enterprise Messaging.

cl_http_utility=>set_request_uri(

        EXPORTING

            request = lo_http_client_messaging->request

            uri     = '/messagingrest/v1/queues/{queue_name}/messages'

    ).




    DATA(lo_request) = lo_rest_messaging->if_rest_client~create_request_entity( ).




    lo_request->set_header_field(

      EXPORTING

        iv_name  = 'x-qos'

        iv_value = '0'

    ).




    lo_request->set_header_field(

      EXPORTING

        iv_name  = 'Authorization'

        iv_value = |{ ls_token-token_type } { ls_token-access_token }|

    ).




    lo_rest_messaging->if_rest_client~post( io_entity = lo_request ).

In order to consume message from a queue use uri

'/messagingrest/v1/queues/{queue}/messages/consumption'.

Let’s use management destination and get some information about queues in our service:

TYPES: BEGIN OF ty_queue,

             name                       TYPE string,

             messagecount               TYPE int4,

             queuesizeinbytes           TYPE int4,

             unacknowledgedmessagecount TYPE int4,

             maxqueuesizeinbytes        TYPE int4,

             maxqueuemessagecount       TYPE int4,

           END OF ty_queue,

           tt_queue TYPE TABLE OF ty_queue WITH KEY name.
DATA lt_queues TYPE tt_queue.




cl_http_utility=>set_request_uri(

        EXPORTING

            request = lo_http_client_management->request

            uri     = '/hub/rest/api/v1/management/messaging/queues/{queue}/statistics'

    ).




    DATA(lo_request) = lo_rest_management->if_rest_client~create_request_entity( ).




    lo_request->set_header_field(

      EXPORTING

        iv_name  = 'x-qos'

        iv_value = '0'

    ).




    lo_request->set_header_field(

      EXPORTING

        iv_name  = 'Authorization'

        iv_value = |{ ls_token-token_type } { ls_token-access_token }|

    ).




    lo_rest_management->if_rest_client~get( ).




    DATA(lv_response) = lo_rest_management->if_rest_client~get_response_entity( )->get_string_data( ).

/ui2/cl_json=>deserialize(

      EXPORTING

        json             = lv_response

      CHANGING

        data             = lt_queues

    ).

Summary

And that’s all – it’s this easy. You can go into documentation and have some fun with available APIs. Remember that not all of them are available in the trial account.

I was using /ui2/cl_json because it’s super convenient to use but you can do it your way.

You can also take a look at a sample class I wrote for consuming Enterprise Messaging here:

Read also:

  1. SAP CPI: Technical guide to build a single XSLT mapping for multiple input types