Skip to Content

After hearing all about websocket technology at Tech-ed last year, I’ve been extremely eager to try it out. I found there were a few great blogs already written about ABAP Push Channels and how to create your own. I recommend reading the following useful blogs and documents to get a good understanding of ABAP Push Channels:


and the following series of blogs by Masoud Aghadavoodi Jolfaei

So in this blog I’m not going to go into detail about what ABAP Push Channels are all about, I’d recommend reading the blogs and documents above for that.
I’m rather going to demonstrate a real-life possible use case for ABAP Push Channels (websockets).  As entertaining as it is seeing it being used for ping pong games, thats unlikely to be very useful in an enterprise environment.

After writing this, I realised that it would be way too large to post as 1 blog. So I have divided it into several parts and each part will be posted in the appropriate space on SCN. See links below:

Please Note that this was all done on an ABAP 740 SP06 backend. Much of this is really new and may not be available or the same in prior versions.

The idea is to build a small UI5 or Web Dynpro ABAP Application to display the users Workflow Inbox. This application can either be run standalone or could even be used as a Side Panel Application in the NWBC client, which would possibly be the most appropriate use since it will always be open and be in the users sight while they are busy with other transactions.

Although I am using workflow as the use case to demo this, truthfully, this can be applied to any application in a very similar manner. These notifications are not only being used to display a message in the application, but also to inform the application that there has been a change and a refresh is necessary, therefore the application can reload the data. A push to pull type scenario. This prevents the need for periodic refreshes or for the user to constantly be pressing the refresh button to see if there have been changes.

Step 1 – Create the ABAP Push Channel


Got transaction SAPC (ABAP Push Channels). Right click on “ABAP Push Channels” and click Create.

001.PNG

Enter the name, in this case ZAPC_WF_NOTIFY. Then save to transport or as local object.

002.PNG

Enter a description then press the Generate Class and Service button.

003.PNG

Once generation is complete you will see the following message:

004.PNG

Navigate into the new generated class ZCL_APC_WS_EXT_ZAPC_WF_NOTIFY. Select IF_APC_WS_EXTENSION~ON_START and press the Redefine button . Then do the same for IF_APC_WS_EXTENSION~ON_MESSAGE.

005.PNG

For now leave the implementations of these methods blank, as we will return to enter the code in here after creating the AMC (ABAP Messaging Channel). Activate the class. Then Save and Activate the ABAP Push Channel.

006.PNG

Step 2 – Create the ABAP Messaging Channel


Goto transaction SAMC and right click on “ABAP Messaging Channels” and press Create.

007.PNG

Enter the name ZAMC_WF_NOTIFY. Then save to transport or as local object.

008.PNG

Enter a Description. Put /workflow_notify in Channels and set Message Type ID to TEXT and Activity Scope to System (User will not allow messages to be sent from one user to another). In order to make the messages user specific, we use the channel extension in bind_message_amc_consumer method call and the create_message_producer calls.

Then add the following entry to list of Authorised Programs:

Authorised Program: ZCL_APC_WS_EXT_ZAPC_WF_NOTIFY (class was created in the previous  step)
Prog. Type: CLAS
Activity: Receive via APC WebSocket

In subsequent steps we will add in an additional entry in Authorised programs to allow the program broadcasting the message to use the ABAP Messaging Channel.

009.PNG

Save and Activate the AMC (ABAP Messaging Channel)

010.PNG

Step 3 – Implement the code for the Messaging Channel in the APC

Go back to the APC class we created in step 1 and now implement the following code in the IF_APC_WS_EXTENSION~ON_START method. We are going to leave the IF_APC_WS_EXTENSION~ON_MESSAGE method blank as in this use case the client won’t be sending any messages back to the ABAP backend. However, if it were to do so, we would need to add code into this method to handle it.

METHOD if_apc_ws_extension~on_start .
     
DATA: lv_channel_ext TYPE amc_channel_extension_id.

      TRY.
* Set the Channel extension to the user who is connecting,

* this is to ensure the user in a specific client only receives their own messages   

      lv_channel_ext = sy-mandt && syuname.

* Bind the APC (Websocket) we created in step 1 to the AMC ABAP Messagin Channel we created in step 2   

      DATA(lo_binding)= i_context->get_binding_manager( ).
      lo_binding->bind_amc_message_consumer( i_application_id  = ‘ZAMC_WF_NOTIFY’

                                             i_channel_id      = ‘/workflow_notify’

                                             i_channel_extension_id = lv_channel_ext ).
     

     CATCH cx_apc_error INTO DATA(lx_apc_error).
          DATA(lv_message) = lx_apc_error->get_text( ).

          MESSAGE lx_apc_error->get_text( ) TYPE ‘E’.
     ENDT
RY.

ENDMETHOD.

In the next part we will create the work item exits which will broadcast the message via the ABAP Messaging Channel.

See Real-time notifications and workflow using ABAP Push Channels (websockets) Part 2: Broadcasting the message via Workitem exits

To report this post you need to login first.

11 Comments

You must be Logged on to comment or reply to a post.

  1. Ekansh Saxena

    Hi Brad,

    I saw that if you use Activity Scope as User, it will send the message to the same user who is sending it.

    Can we send message to a specific user using AMC?




    (0) 
    1. Brad Pokroy Post author

      Hi Ekansh,

      Yes you can, you would use the activity scope as system and use the channel extension to specify the user as shown above in this blog or as shown below:

      * Set the Channel extension to the user who is connecting,

      * this is to ensure the user in a specific client only receives their own messages  

            lv_channel_ext = sy-mandt && syuname.

      * Bind the APC (Websocket) we created in step 1 to the AMC ABAP Messagin Channel we createdin step 2  

            DATA(lo_binding)= i_context->get_binding_manager( ).
            lo_binding->bind_amc_message_consumer( i_application_id  =‘ZAMC_WF_NOTIFY’

                                                   i_channel_id      =‘/workflow_notify’

                                                   i_channel_extension_id =lv_channel_ext ).



      If you choose Activity scope user then you will not be able to communicate between different users.

      Cheers,

      Brad

      (0) 
      1. Ekansh Saxena

        Hello Brad,

        I am using an AMC with scope as System, the receiver program has activity as Receive via session. I included channel extension in sender as well as receiver program such that the channel extension is like “100USER2” (100 is the client and USER2 is the user to whom I want to send the message). I logged in with two different users(USER1 & USER2) and run the receiver report. The problem is that message is getting received by both the users.

        Can you help please?

        (0) 
          1. Ekansh Saxena

            Hi Brad,

            The code for sending is:

            REPORT zdemo_send_amc.

            CLASS demo DEFINITION.

              PUBLIC SECTION.

                CLASS-METHODS main.

            ENDCLASS.

            CLASS demo IMPLEMENTATION.

              METHOD main.

                DATA: lv_channel_ext TYPE amc_channel_extension_id,

                      lv_uname type sy-uname.

                lv_uname = ‘USER2’.

                lv_channel_ext = sy-mandt && lv_uname.

                TRY.

                    CAST if_amc_message_producer_text(

                           cl_amc_channel_manager=>create_message_producer(

                             i_application_id = ‘ZAMC_XXXX_TEST’

                             i_channel_id     = ‘/XXXX_test’

                             i_channel_extension_id = lv_channel_ext )

                      )->send( i_message = |Message from Ekansh by { sy-repid }| ).

                  CATCH cx_amc_error INTO DATA(text_exc).

                    cl_demo_output=>display( text_exc->get_text( ) ).

                ENDTRY.

              ENDMETHOD.

            ENDCLASS.

            START-OF-SELECTION.

              demo=>main( ).

            The code for receiving is:

            REPORT zdemo_receive_amc_new.

            CLASS message_receiver DEFINITION.

              PUBLIC SECTION.

                INTERFACES: if_amc_message_receiver_text.

                DATA: text_message TYPE string.         

            ENDCLASS.

            CLASS message_receiver IMPLEMENTATION.

              METHOD if_amc_message_receiver_text~receive.

                text_message = i_message.

              ENDMETHOD.

            ENDCLASS.

            CLASS amc_demo DEFINITION.

              PUBLIC SECTION.

                CLASS-METHODS main.

            ENDCLASS.

            CLASS amc_demo IMPLEMENTATION.

              METHOD main.

                DATA: lv_channel_ext TYPE amc_channel_extension_id,

                      lv_uname type sy-uname.

                lv_uname = ‘USER2’.

                lv_channel_ext = sy-mandt && lv_uname.

                DATA(receiver) = NEW message_receiver( ).

                TRY.

                    cl_amc_channel_manager=>create_message_consumer(

                        i_application_id = ‘ZAMC_XXXX_TEST’

                        i_channel_id     = ‘/XXXX_test’

                        i_channel_extension_id = lv_channel_ext

                        )->start_message_delivery( i_receiver = receiver ).

                  CATCH cx_amc_error INTO DATA(text_exc).

                    cl_demo_output=>display( text_exc->get_text( ) ).

                ENDTRY.

                WAIT FOR MESSAGING CHANNELS

                     UNTIL receiver->text_message   IS NOT INITIAL               

                     UP TO 5 SECONDS.

                cl_demo_output=>begin_section( receiver->text_message ).

              ENDMETHOD.

            ENDCLASS.

            START-OF-SELECTION.

              amc_demo=>main( ).

            (0) 
            1. Brad Pokroy Post author

              Hi Ekansh,

              It appears to be correct to me and similar to what I did. The only difference is I setup a class to receive via an APC websocket and have the receiver code in the following method:METHOD if_apc_ws_extension~on_start. Which is triggered via an external UI5 app or web dynpro.

              Maybe try putting the receiver into an APC websocket class and in the on~start method. Then use the webdynpro component/application WDR_TEST_APC to test it. Try logon with both users and connect to it with both users and see if it still gives you that issue.

              Cheers,

              Brad

              (0) 
            2. Manish Majumdar

              Hi Ekansh,

              I see you are using just a single extension id in the above code. Until you use two different extension id’s all the messages which are sent to that specific channel/extension ID combination would be received by all the users who are running this receiver report.

              Regards,

              Manish

              (0) 

Leave a Reply