Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
bradp
Active Participant

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.aghadavoodijolfaei

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.

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

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

Once generation is complete you will see the following message:

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.

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.

Step 2 – Create the ABAP Messaging Channel


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

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

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.

Save and Activate the AMC (ABAP Messaging Channel)

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 && sy-uname.

* 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 ...

13 Comments
js2
Product and Topic Expert
Product and Topic Expert
0 Kudos

Great blog series Brad - Thanks!!!

bradp
Active Participant
0 Kudos

Thanks Jason!

EkanshCapgemini
Active Contributor
0 Kudos

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?




bradp
Active Participant
0 Kudos

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 && sy-uname.

* 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

EkanshCapgemini
Active Contributor
0 Kudos

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?

bradp
Active Participant
0 Kudos

Hi Ekansh,

Can you post the code for me to see please.

Cheers,

Brad

EkanshCapgemini
Active Contributor
0 Kudos

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( ).

bradp
Active Participant
0 Kudos

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

manuish02
Explorer
0 Kudos

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

EkanshCapgemini
Active Contributor
0 Kudos

Hi Manish,

Can you explain how can I use two different extension ids while sending the message.

jonantansousa
Explorer
0 Kudos
Hi Brad!

Will this only work if the fiori client is open or this work like a gmail push notification?
deepthi_b
Participant
0 Kudos
Hi Brad,

How can we communicate to Non SAP system through ABAP channel.

We want to send the Notification data thru Websocket to NON SAP system. Able to test the ABAP Channel from Browser but  the NON SAP system is unable to receive the data sent from SAP even though they add our WSS URL in their application.

Before calling ABAP push channel do we need to establish communication between SAP and NON  SAP system? If possible kindly share how to do that.

 

Thanks & Regards

Deepthi
deepthi_b
Participant
0 Kudos
Hi Brad,

We are trying to connect to NON SAP system thru ABAP Channel . Able to test the ABAP channel from web  .Non SAP system added ABAP channel  wss URL in their application but they are unable to receive any message from SAP.

Before calling Abap push channel do we need to establish connectivity with Non SAP system? If so how should that be done.

 

Thanks & Regards

Deepthi
Labels in this area