Skip to Content
Author's profile photo Brad Pokroy

Real-time notifications and workflow using ABAP Push Channels (websockets) Part 4: Creating a Web Dynpro ABAP Application for receiving notifications

This is Part 4 of the below series of blogs:

Now we are going to create a similar application to what we did in Part 3, however this time we are going to use APC (websockets) in a Web Dynpro ABAP application. We do this using a fairly new feature called HTML Islands.

Create a new Web Dynpro ABAP component called ZWDC_WF_INBOX_MINI

024.PNG

In the Component Controller create a new Node

025.PNG

Enter the following:
Node Name: WORKITEMS
Dictionary structure: SWR_WIHDR
Cardinality: 0..n
Init. Lead Selection: No

Then press the Add Attributes from Structure button

026.PNG

Select the WI_TEXT, WI_CD and WI_CT attributes and press the green tick

027.PNG

Create a new method GET_USER_WORKITEMS is the Component Controller and put the following code in it:

028.PNG

METHOD get_user_workitems .
     
DATA: lo_nd_workitems TYPE REF TO if_wd_context_node.

      DATA: lt_workitems TYPE wd_this->elements_workitems.

      lo_nd_workitems = wd_context->get_child_node( name = wd_this->wdctx_workitems ).

      CALL FUNCTION ‘SAP_WAPI_CREATE_WORKLIST’
          
TABLES
                worklist
= lt_workitems.

      SORT lt_workitems BY wi_id DESCENDING.

      lo_nd_workitems->bind_table( new_items = lt_workitems set_initial_elements = abap_true ).

ENDMETHOD.

Then add the following code to the WDDOINIT Method:

METHOD wddoinit .
      wd_this
->get_user_workitems( ).
ENDMETHOD.

In the V_MAIN View, go to Context and map WORKITEMS to CONTEXT by dragging and dropping it from the right side to the left side.

030.PNG

Go into Layout tab and start by changing the ROOTUIELEMENTCONTAINER Layout to a RowLayout:

031.PNG

Right click on ROOTUIELEMENTCONTAINER and click Insert Element.

032.PNG

Enter the following:
ID: WS_HTML_ISLAND
Typ: HtmlIsland

033.PNG

Select WS_HTML_ISLAND and change the height and width to 0px as we do not want this HTML Island to be visible.

034b.PNG

Now right click on WS_HTML_ISLAND and click on Insert Event.

035.PNG

Give the Event a name ON_MESSAGE and the press the Create button next to onAction to Create an event handler.

036.PNG

Enter the Action name as ON_MESSAGE and make sure to tick Transfer UI Event Parameters, then press the green tick.

037.PNG

Double click on the ON_MESSAGE action created to forward navigate into the method. Then paste in the code below

038.PNG

METHOD onactionon_mesage .
     
DATA: lo_api_controller     TYPE REF TO if_wd_controller.

      lo_api_controller ?= wd_this->wd_get_api( ).

*   report message
      lo_api_controller
->get_message_manager( )->report_message( message_text = data
                                                                message_type
= if_wd_message_manager=>co_type_info
                                                                is_permanent
= abap_false  ).
* refresh work items
      wd_comp_controller
->get_user_workitems( ).
ENDMETHOD.

Go back into the Layout tab and right click on WS_HTML_ISLAND again and add a script this time.

039.PNG

Enter in websocket_wf_notify.js in the source field. We wil create and upload this javascript file afterwards.

040.PNG

Save the following source to a file name websocket_wf_notify.js and upload it as a MIME object for the webdynpro.

Source code:

var MySocket = { 

      init: function(callback){

            //Save the call back object to this object

            this.callback = callback;

            var that = this;

            var hostLocation = window.location, socket, socketHostURI, webSocketURI;

            if (hostLocation.protocol === “https:”) {

                  socketHostURI = “wss:”;

            } else {

                  socketHostURI = “ws:”;

            }

            socketHostURI += “//” + hostLocation.host;

            webSocketURI = socketHostURI + ‘/sap/bc/apc/sap/zapc_wf_notify’;

       

            try {

                  socket = new WebSocket(webSocketURI);

                  socket.onopen = function() { };

                  var that = this;

  

                  //Create function for handling websocket messages

                  socket.onmessage = function(wfNotify) {

                        // When a message is received fire an event to call the web dynpro code to post the message and

                        // refresh the worklist

                        that.callback.fireEvent(‘ON_MESSAGE’, wfNotify.data);

                  };

  

                  socket.onclose = function() {

                  };

            } catch (exception) {

  

            }

      }

};

Right click on the web dynpro component and go to Create->Mime Object->Import.

041.PNG

Select the file you created in the previous step websocket_wf_notify.js and click open.

042.PNG

Then press save.

043.PNG

Right click on ROOTUIELEMENTCONTAINER again and Insert Element.

044.PNG

And enter MESSAGE_AREA and select MessageArea as the Type.

045.PNG

Make sure ROOTUIELEMENTCONTAINER is selected and then press the Wizard button

046.PNG

Select Table and press Continue.

047.PNG

Press Context to select the WORKITEMS context:

048.PNG

Select WORKITEMS and press the green tick.

049.PNG

No Need to change anything on the next screen, just press the green tick.

In the table properties change design to Alternating and set visibleRowCount to 25.

051.PNG

Now go into the Methods tab and select the WDDOMODIFYVIEW method.

And enter the following code to initialise the web socket when the view first loads:

METHOD wddomodifyview .
     
DATA: lo_html_island TYPE REF TO cl_wd_html_island.

      IF first_time EQ abap_true.

           lo_html_island ?= view->get_element( `WS_HTML_ISLAND` ).

           lo_html_island->add_script_call( cl_wd_html_script_call=>new_call( )->variable( `MySocket` )->function( `init` )->add_callback_api( )  ).
     
ENDIF.
ENDMETHOD.

Right click on ZWDC_WF_INBOX_MINI and go to Create->Web Dynpro Application.

Enter an application name and Description and press the green tick.

054.PNG

Save and activate everything then right click the Web Dynpro application to run.

Now open the window next to the SAP GUI and create a new parked journal, which will go to my inbox for approval. On saving the Parked Journal document, the notification is immediately displayed in my browser window and the list is automatically refreshed.

Before saving:

056.PNG

After SavingInbox updated with new document automatically and notification displayed:

057.PNG

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hi Brad Pokroy,

      It's a very useful blog.Keep-up the excellent work & keep blogging.

      And i'm the first person to bookmark your blog.  😉

      Thanks

      Katrice

      Author's profile photo Kirill Smirnov
      Kirill Smirnov

      Thanks Brad,
      Excellent blog!

      Author's profile photo Ramakrishna Thoodi
      Ramakrishna Thoodi

      Hi Brad,

      Really good, thanks.

      Author's profile photo Brad Pokroy
      Brad Pokroy
      Blog Post Author

      Thanks Katrice, Kirill and Ramakrishna! I appreciate your feedback 🙂

      Author's profile photo Former Member
      Former Member

      Hi Brad,

      This one is a really helpful blog for me as we were trying a way to avoid Webdynpro Notifications because of its polling mechanism on ICM to check if the particular event had occured or not. Your Blog is really helpful for me.

      Regards,

      Manish

      Author's profile photo Brad Pokroy
      Brad Pokroy
      Blog Post Author

      Thanks Manish! Good to hear you found it useful 🙂

      Cheers,

      Brad

      Author's profile photo Manish Majumdar
      Manish Majumdar

      HI Brad,

      Is there any way I can add another parameter value in init method of your Javascript and pass that value from WDDOMODIFY when we call the add_Script_call method? What I want to achive is to pass a value from my initi method and I would concatenate that value as a URL parameter of the service of the APC.

      Regards,

      Manish

      Author's profile photo Brad Pokroy
      Brad Pokroy
      Blog Post Author

      Hi Manish,

      Interesting question. I had to try it out to figure out the answer. But the answer is yes you can.

      I did this by adding on an additional method chain call. see below:

      lo_html_island->add_script_call( cl_wd_html_script_call=>new_call( )->variable( `MySocket` )->function( `init` )->add_callback_api( )->add_string('hello').


      Here by adding on the ->add_string('hello') after the add_callback_api( ) it passes through the string hello in the second parameter I would now need to add to my init function as the second import parameter.

      ws_abap_wd.PNG

      See above I added sParam and it contains the value "hello" which is passed in from the web dynpro. So in the JavaScript you would just need to add some code to do whatever you want to do with that value.

      Cheers,

      Brad

      Author's profile photo Manish Majumdar
      Manish Majumdar

      It worked for me Brad. Thanks for your reply.

      But I am trying something different now. I am trying to use a PCP type message in my ABAP channel and consuming it in my Webdynpro Do you think the action handler method would be able to handle it? Because it just have a data of type string...I am just thinking how to use that. I saw the serialize/deserialize methods in PCP_Producer interface.

      I am not able to connect the dots and make it work. 😥 😥 😥

      Could you please help me here?

      Regards,

      Manish

      Author's profile photo Former Member
      Former Member

      Hi Brad Pokroy,

      Thanks for Sharing The Knowledge.  and i have one Doubt in my Development.

      is it Posible To Pass any parameter from Back end and Retrieve it in WD Componet??

      If it so, how to Achieve it??

      Pls Help me.

      Thanks in Advance.

      Author's profile photo Laszlo Liptai
      Laszlo Liptai

      Really useful blog about using APC in WebDynpro Application! It helped me a lot.

      But meanwhile there has been a change in APC creation: Protocol Specification has been introduced.

      The protocol has to be also provided in the javascript during WebSocket creation, otherwise that will not work.

      SAPC:

      APC protocol.png


      Related javascript code line:


      socket = new WebSocket(webSocketURI, 'v10.pcp.sap.com');

      Author's profile photo Manish Majumdar
      Manish Majumdar

      Hi Laszio,

      Is this protocol specification made mandatory on all the versions? We are on NEtweaver 7.40 SP 9 and for us it works fine without implementing the protocol name.

      Regards,

      Manish

      Author's profile photo Laszlo Liptai
      Laszlo Liptai

      Hi Manish,

      My post is just a remark. I used the given javascript example provided by this blog but my test WD application didn't work. I was struggling with it for a while, after that I realized this protocol stuff.
      This protocol specification is introduced in higher NetWeaver version than 7.40

      The point is that, if you don't see it in transaction SAPC just ignore it.

      Regards,

      Laszlo

      Author's profile photo Former Member
      Former Member

      Hi

       

      Your post is very useful with all the examples as well as the ABAP webdynpro front end.

      If my requirement is to integrate with a device that communicate via the websocket, is it sufficient to just do the ABAP webdypro with *.js to get the client information and APC? Is it necessary to still configure the AMC?

       

      Rgds

      Rusyinni