diff --git a/src/00/z2ui5_cl_demo_app_s_05.clas.abap b/src/00/z2ui5_cl_demo_app_s_05.clas.abap
index 597292a4..5c6de4a6 100644
--- a/src/00/z2ui5_cl_demo_app_s_05.clas.abap
+++ b/src/00/z2ui5_cl_demo_app_s_05.clas.abap
@@ -1,13 +1,187 @@
-class Z2UI5_CL_DEMO_APP_S_05 definition
- public
- create public .
+CLASS z2ui5_cl_demo_app_s_05 DEFINITION PUBLIC.
+
+ PUBLIC SECTION.
+
+ TYPES:
+ BEGIN OF t_news,
+ text TYPE string,
+ author TYPE string,
+ END OF t_news,
+ tt_News TYPE STANDARD TABLE OF t_news
+ WITH NON-UNIQUE DEFAULT KEY.
+
+ INTERFACES z2ui5_if_app.
+ DATA news_input TYPE string.
+ DATA author_input TYPE string.
+ DATA news_list TYPE tt_News.
+ DATA connections TYPE int8.
+
+ PROTECTED SECTION.
+ DATA client TYPE REF TO z2ui5_if_client.
+
+ METHODS z2ui5_on_event.
+ METHODS z2ui5_on_render.
+ METHODS z2ui5_display_popover.
+
+ PRIVATE SECTION.
-public section.
-protected section.
-private section.
ENDCLASS.
+CLASS z2ui5_cl_demo_app_s_05 IMPLEMENTATION.
+
+ METHOD z2ui5_if_app~main.
+
+ me->client = client.
+
+ IF me->z2ui5_if_app~check_initialized = abap_false.
+ connections = z2ui5_cl_demo_app_s_05_ws=>get_active_connections( ).
+ ENDIF.
+
+ IF client->get( )-event IS NOT INITIAL.
+ z2ui5_on_event( ).
+ client->view_model_update( ).
+ RETURN.
+ ENDIF.
+
+ z2ui5_on_render( ).
+
+ ENDMETHOD.
+
+
+ METHOD z2ui5_on_event.
+ DATA: news TYPE t_news.
+
+ CASE client->get( )-event.
+ WHEN `CLEAR`.
+
+ CLEAR: news_list.
+
+ WHEN 'BACK'.
+
+ client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
+
+ WHEN 'CLICK_HINT_ICON'.
+
+ z2ui5_display_popover( ).
+
+ ENDCASE.
+
+ ENDMETHOD.
+
+
+ METHOD z2ui5_on_render.
+
+ DATA(view) = z2ui5_cl_xml_view=>factory( ).
+ DATA(page) = view->shell(
+ )->page(
+ title = 'abap2UI5 - Sample: News Feed over WebSocket'
+ navbuttonpress = client->_event( 'BACK' )
+ shownavbutton = xsdbool( client->get( )-s_draft-id_prev_app_stack IS NOT INITIAL ) ).
+
+ page->header_content(
+ )->button( id = `button_hint_id`
+ icon = `sap-icon://hint`
+ tooltip = `Sample information`
+ press = client->_event( 'CLICK_HINT_ICON' ) ).
+
+ DATA(form) = page->simple_form( editable = abap_true
+ title = `Publish news`
+ class = `sapUiTinyMarginBottom`
+ )->content( `form` ).
+
+ form->feed_input(
+ value = client->_bind_edit( news_input )
+ post = client->_event_client(
+ val = `Z2UI5`
+ t_arg = VALUE #( ( `feedInputPost` ) )
+ ) ).
+
+ form->label( text = `Author`
+ )->input( value = client->_bind_edit( author_input )
+ placeholder = `Anonymous` ).
+
+ page->list(
+ headertext = `News`
+ items = client->_bind_edit( news_list )
+ )->feed_list_item(
+ sender = `{AUTHOR}`
+ text = `{TEXT}`
+ showicon = abap_false ).
+
+ DATA(footer) = page->footer( )->overflow_toolbar( ).
+ footer->info_label(
+ text = client->_bind_edit( connections )
+ colorscheme = `7`
+ icon = `sap-icon://connected` ).
+
+ footer->toolbar_spacer( )->button(
+ text = `Clear`
+ icon = `sap-icon://clear-all`
+ press = client->_event( `CLEAR` ) ).
+
+ IF me->z2ui5_if_app~check_initialized = abap_false.
+ view->_generic( name = `script`
+ ns = `html`
+ )->_cc_plain_xml(
+ `(()=>{ ` &&
+ ` const ws_url = (window.location.origin + '/sap/bc/apc/sap/z2ui5_sample').replace('http','ws');` &&
+ ` try { ` &&
+ ` ws = new WebSocket(ws_url);` &&
+ ` } catch (err) {` &&
+ ` alert(err);` &&
+ ` }` &&
+ ` ws.onopen = ()=>{};` &&
+ ` ws.onmessage = (msg)=>{` &&
+ ` const model = z2ui5.oController.oView.getModel();` &&
+ ` const data = model.getData();` &&
+ ` if (msg.data === '` && z2ui5_cl_demo_app_s_05_ws=>c_msg-__new_connection__ && `') {` &&
+ ` data.XX.CONNECTIONS += 1;` &&
+ ` } else if (msg.data === '` && z2ui5_cl_demo_app_s_05_ws=>c_msg-__closed__ && `') {` &&
+ ` data.XX.CONNECTIONS -= 1;` &&
+ ` } else {` &&
+ ` data.XX.NEWS_LIST.push(JSON.parse(msg.data));` &&
+ ` }` &&
+ ` model.setData(data);` &&
+ ` };` &&
+ ` ws.onclose = (msg)=>{};` &&
+ `})()` ).
+
+ view->_generic( name = `script`
+ ns = `html`
+ )->_cc_plain_xml(
+ `z2ui5.feedInputPost = () => { ` &&
+ ` const model = z2ui5.oView.getModel();` &&
+ ` const data = model.getData();` &&
+ ` ws.send(JSON.stringify({ ` &&
+ ` TEXT : data.XX.NEWS_INPUT,` &&
+ ` AUTHOR : data.XX.AUTHOR_INPUT ` &&
+ ` }));` &&
+ ` setTimeout( () => { ` &&
+ ` data.XX.NEWS_INPUT = "";` &&
+ ` model.setData(data);` &&
+ ` }, 10 ); ` &&
+ `}` ).
+ ENDIF.
+
+ client->view_display( view->stringify( ) ).
+
+ ENDMETHOD.
+
+
+ METHOD z2ui5_display_popover.
+
+ DATA(view) = z2ui5_cl_xml_view=>factory_popup( ).
+ view->quick_view( placement = `Bottom`
+ width = `auto`
+ )->quick_view_page( pageid = `sampleInformationId`
+ header = `Sample information`
+ description = `This sample show how to consume APC-Messages over websocket. Open the app mutliple times and post something.` ).
+
+ client->popover_display(
+ xml = view->stringify( )
+ by_id = `button_hint_id` ).
+
+ ENDMETHOD.
-CLASS Z2UI5_CL_DEMO_APP_S_05 IMPLEMENTATION.
ENDCLASS.
diff --git a/src/00/z2ui5_cl_demo_app_s_05.clas.xml b/src/00/z2ui5_cl_demo_app_s_05.clas.xml
index 4a1b746e..25a51505 100644
--- a/src/00/z2ui5_cl_demo_app_s_05.clas.xml
+++ b/src/00/z2ui5_cl_demo_app_s_05.clas.xml
@@ -1,4 +1,16 @@
-
+
+
+
+ Z2UI5_CL_DEMO_APP_S_05
+ E
+ News Feed over Websocket
+ 1
+ X
+ X
+ X
+
+
+
diff --git a/src/00/z2ui5_cl_demo_app_s_05_ws.clas.abap b/src/00/z2ui5_cl_demo_app_s_05_ws.clas.abap
index b470bc66..289c0556 100644
--- a/src/00/z2ui5_cl_demo_app_s_05_ws.clas.abap
+++ b/src/00/z2ui5_cl_demo_app_s_05_ws.clas.abap
@@ -1,13 +1,107 @@
-class Z2UI5_CL_DEMO_APP_S_05_WS definition
- public
- create public .
+CLASS z2ui5_cl_demo_app_s_05_ws DEFINITION PUBLIC
+ INHERITING FROM cl_apc_wsp_ext_stateless_base.
+
+ PUBLIC SECTION.
+
+ CLASS-METHODS: get_active_connections
+ RETURNING
+ VALUE(result) TYPE i.
+
+ METHODS:
+ if_apc_wsp_extension~on_message REDEFINITION,
+ if_apc_wsp_extension~on_start REDEFINITION,
+ if_apc_wsp_extension~on_close REDEFINITION.
+
+ CONSTANTS:
+ c_amc_application_id TYPE amc_application_id VALUE 'Z2UI5_SAMPLE' ##NO_TEXT,
+ c_channel_id TYPE amc_channel_id VALUE '/news_feed' ##NO_TEXT,
+ BEGIN OF c_msg,
+ __new_connection__ TYPE string VALUE `__NEW_CONNECTION__` ##NO_TEXT,
+ __closed__ TYPE string VALUE `__CLOSED__` ##NO_TEXT,
+ END OF c_msg.
+
+ PRIVATE SECTION.
+
+ CLASS-METHODS:
+ get_producer
+ RETURNING
+ VALUE(producer) TYPE REF TO if_amc_message_producer_text
+ RAISING
+ cx_amc_error,
+ send
+ IMPORTING
+ i_message TYPE string
+ RAISING
+ cx_amc_error.
-public section.
-protected section.
-private section.
ENDCLASS.
+CLASS z2ui5_cl_demo_app_s_05_ws IMPLEMENTATION.
+
+ METHOD get_producer.
+
+ producer ?= cl_amc_channel_manager=>create_message_producer( i_application_id = c_amc_application_id
+ i_channel_id = c_channel_id ).
+
+ ENDMETHOD.
+
+
+ METHOD if_apc_wsp_extension~on_message.
+
+ TRY.
+ send( i_message->get_text( ) ).
+ CATCH cx_root INTO DATA(error).
+ RAISE SHORTDUMP error.
+ ENDTRY.
+
+ ENDMETHOD.
+
+
+ METHOD if_apc_wsp_extension~on_start.
+
+ TRY.
+
+ i_context->get_binding_manager(
+ )->bind_amc_message_consumer( i_application_id = c_amc_application_id
+ i_channel_id = c_channel_id ).
+
+ get_producer( )->send( c_msg-__new_connection__ ).
+
+ CATCH cx_root INTO DATA(error).
+ RAISE SHORTDUMP error.
+ ENDTRY.
+
+ ENDMETHOD.
+
+
+ METHOD if_apc_wsp_extension~on_close.
+
+ TRY.
+ get_producer( )->send( c_msg-__closed__ ).
+
+ CATCH cx_root INTO DATA(error).
+ RAISE SHORTDUMP error.
+ ENDTRY.
+
+ ENDMETHOD.
+
+
+ METHOD get_active_connections.
+
+ SELECT
+ FROM amc_receiver2
+ FIELDS COUNT( * )
+ WHERE channel_id = @( to_lower( |{ c_amc_application_id }{ c_channel_id }| ) )
+ INTO @result.
+
+ ENDMETHOD.
+
+
+ METHOD send.
+
+ get_producer( )->send( i_message ).
+
+ ENDMETHOD.
-CLASS Z2UI5_CL_DEMO_APP_S_05_WS IMPLEMENTATION.
ENDCLASS.
diff --git a/src/00/z2ui5_cl_demo_app_s_05_ws.clas.xml b/src/00/z2ui5_cl_demo_app_s_05_ws.clas.xml
index 4a1b746e..88a8a13d 100644
--- a/src/00/z2ui5_cl_demo_app_s_05_ws.clas.xml
+++ b/src/00/z2ui5_cl_demo_app_s_05_ws.clas.xml
@@ -1,4 +1,16 @@
-
+
+
+
+ Z2UI5_CL_DEMO_APP_S_05_WS
+ E
+ Generated APC WebSocket protocol impementation class
+ 1
+ X
+ X
+ X
+
+
+
diff --git a/src/00/z2ui5_sample.samc.xml b/src/00/z2ui5_sample.samc.xml
index d5b0bc3c..15a48b4e 100644
--- a/src/00/z2ui5_sample.samc.xml
+++ b/src/00/z2ui5_sample.samc.xml
@@ -28,7 +28,7 @@
A
1
/news_feed
- Z2UI5_CL_DEMO_APP_352_WS======CP
+ Z2UI5_CL_DEMO_APP_S_05_WS=====CP
S
@@ -36,7 +36,7 @@
A
2
/news_feed
- Z2UI5_CL_DEMO_APP_352_WS======CP
+ Z2UI5_CL_DEMO_APP_S_05_WS=====CP
C
diff --git a/src/00/z2ui5_sample.sapc.xml b/src/00/z2ui5_sample.sapc.xml
index a9e5ece1..8f9c505b 100644
--- a/src/00/z2ui5_sample.sapc.xml
+++ b/src/00/z2ui5_sample.sapc.xml
@@ -7,7 +7,7 @@
Z2UI5_SAMPLE
A
/sap/bc/apc/sap/z2ui5_sample
- Z2UI5_CL_DEMO_APP_352_WS
+ Z2UI5_CL_DEMO_APP_S_05_WS
1