ICEfaces
  1. ICEfaces
  2. ICE-4768

Callbacks for bridge lifecycle

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-Alpha2
    • Component/s: Bridge
    • Labels:
      None
    • Environment:
      bridge
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.)

      Description

      It would be nice to have callbacks for bridge lifecycle (e.g.)

      - ice.onSubmit(function(params) {

      })

      - ice.onUpdateReceived (function(response) {

      })

      - ice.onUpdateCompleted(function() {

      })

        Issue Links

          Activity

          Hide
          Ken Fyten added a comment -

          Assign to Deryk for Core team consideration.

          Show
          Ken Fyten added a comment - Assign to Deryk for Core team consideration.
          Hide
          Mircea Toma added a comment -

          Here is a compiled list of functions that can be used to register callbacks with a bridge instance ("ice" namespace is implied):

          function onSubmit(callbackBefore, callbackAfter)

          { //callbackBefore receives the parameters of the submit callbackBefore(parameters); //callbackAfter receives the body of the response callbackAfter(responseContent); }

          function onDOMUpdate(callbackBefore, callbackAfter)

          { //... //callbackBefore receives the updating element callbackBefore(updateElement); //callbackAfter receives the element found in the DOM document after the update callbackAfter(updatedFragment); }

          function onConnectionDown(callback)

          { //... }

          function onPongLost(callback) { //... //callback receives the number of consecutive lost pongs callback(numberOfConsecutivePongsLost); //... }

          function onBlockingConnectionDown(callback) {
          }

          function onServerError(callback) { //... //callback receives the error code and body of the error response callback(errorCode, message); //... }

          function onViewDisposal(callback) { //... //callback receives the identifier of the view that is about to be disposed callback(viewStateID); //... }

          function onSessionExpired(callback) { //... }
          Show
          Mircea Toma added a comment - Here is a compiled list of functions that can be used to register callbacks with a bridge instance ("ice" namespace is implied): function onSubmit(callbackBefore, callbackAfter) { //callbackBefore receives the parameters of the submit callbackBefore(parameters); //callbackAfter receives the body of the response callbackAfter(responseContent); } function onDOMUpdate(callbackBefore, callbackAfter) { //... //callbackBefore receives the updating element callbackBefore(updateElement); //callbackAfter receives the element found in the DOM document after the update callbackAfter(updatedFragment); } function onConnectionDown(callback) { //... } function onPongLost(callback) { //... //callback receives the number of consecutive lost pongs callback(numberOfConsecutivePongsLost); //... } function onBlockingConnectionDown(callback) { } function onServerError(callback) { //... //callback receives the error code and body of the error response callback(errorCode, message); //... } function onViewDisposal(callback) { //... //callback receives the identifier of the view that is about to be disposed callback(viewStateID); //... } function onSessionExpired(callback) { //... }
          Hide
          Deryk Sinotte added a comment -

          I believe there's a balance between overly generic and overly specific APIs in this case. My recommendation for the connection related methods:

          function onConnectionDown(callback)
          function onPongLost(callback)
          function onBlockingConnectionDown(callback)

          would be to define a single method something like this:

          function addOnConnectionEvent(callback)

          or, in keeping with our other decision to provide separate registration methods for before/after type processing:

          function addOnConnectionEventBefore(callback)
          function addOnConnectionEventAfter(callback)

          and then provide the callback function with an connectionEvent parameter that contains relevant invformation. Based on that foundational method, we could then provide utility methods like the original ones mentioned above, but the original method could also be used by developers to use in ways we may not have anticipated.

          If the number of events becomes large, then perhaps a filtering mechanism might be added in as well as an optional parameter.

          function addOnConnectionEventBefore(callback, eventFilter)
          function addOnConnectionEventAfter(callback, eventFilter)

          Show
          Deryk Sinotte added a comment - I believe there's a balance between overly generic and overly specific APIs in this case. My recommendation for the connection related methods: function onConnectionDown(callback) function onPongLost(callback) function onBlockingConnectionDown(callback) would be to define a single method something like this: function addOnConnectionEvent(callback) or, in keeping with our other decision to provide separate registration methods for before/after type processing: function addOnConnectionEventBefore(callback) function addOnConnectionEventAfter(callback) and then provide the callback function with an connectionEvent parameter that contains relevant invformation. Based on that foundational method, we could then provide utility methods like the original ones mentioned above, but the original method could also be used by developers to use in ways we may not have anticipated. If the number of events becomes large, then perhaps a filtering mechanism might be added in as well as an optional parameter. function addOnConnectionEventBefore(callback, eventFilter) function addOnConnectionEventAfter(callback, eventFilter)
          Hide
          Mircea Toma added a comment - - edited

          Okay, I will try to split down aspects of the discussion we have here.
          First, I'll talk about the generic connection related event notification. I still believe this is an idea that comes from Java world were developers are used to program in certain ways, but exactly these kind of "design patterns" brought in so much verbosity just for the sake of having common denominator conventions.
          Let's see how an API user will register a callback with the API proposed by Deryk:

          addOnConnectionEvent(function(event) {
          if (event.type == 'submit') {
          if (event.phase == 'before')

          { //ah, it's the 'before' phase...we must have 'parameters' shoved into the event var parameters = event.parameters; //.... //execute the code for submit/before event //.... }

          }
          });

          addOnConnectionEvent(function(event) {
          if (event.type == 'submit') {
          if (event.phase == 'after')

          { //ah, it's the 'after' phase...we must have the responseText shoved into the event var responseText = event.responseText; //.... //execute the code for submit/after event //.... }

          }
          });

          addOnConnectionEvent(function(event) {
          if (event.type == 'blocking-connection-unstable')

          { //ah, it's the 'after' phase...we must have the lostPongs shoved into the event var lostPongs = event.lostPongs; //.... //execute the code for submit/after event //.... }

          });

          Now if we want to filter the events as defined by addOnConnectionEventBefore(callback, eventFilter) function we have the "boiler plate" code for filters:

          function submitBeforefilter(event, callback) {
          if (event.type == 'submit') {
          if (event.phase == 'before')

          { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event); }
          }
          }

          function submitAfterfilter(event, callback) {
          if (event.type == 'submit') {
          if (event.phase == 'after') { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event); }

          }
          }

          function blockingConnectionUnstable(event, callback) {
          if (event.type == 'connection-unstable')

          { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event) }

          }

          So all this work for determining what kind of event is received has to be done in various parts of the component or application code. Oh, but we have the filters to save us from repeating ourselves. But then why do we need to hide the specificity of the event in the first place?
          Here is the simple version:

          addOnSubmitSend(function(parameters)

          { //no need to query for the event type //parameters are available if needed //...execute the code... }

          );

          addOnSubmitResponse(function(responseText, responseXML)

          { //no need to query for the event type //responseText is available if needed //responseXML is available in case response is in XML format //...execute the code... }

          );

          addOnBlockingConnectionUnstable(function(numberOfReconnectionFailures)

          { //no need to query for the event type //numberOfReconnectionFailures is available if needed //...execute the code... }

          );

          Show
          Mircea Toma added a comment - - edited Okay, I will try to split down aspects of the discussion we have here. First, I'll talk about the generic connection related event notification. I still believe this is an idea that comes from Java world were developers are used to program in certain ways, but exactly these kind of "design patterns" brought in so much verbosity just for the sake of having common denominator conventions. Let's see how an API user will register a callback with the API proposed by Deryk: addOnConnectionEvent(function(event) { if (event.type == 'submit') { if (event.phase == 'before') { //ah, it's the 'before' phase...we must have 'parameters' shoved into the event var parameters = event.parameters; //.... //execute the code for submit/before event //.... } } }); addOnConnectionEvent(function(event) { if (event.type == 'submit') { if (event.phase == 'after') { //ah, it's the 'after' phase...we must have the responseText shoved into the event var responseText = event.responseText; //.... //execute the code for submit/after event //.... } } }); addOnConnectionEvent(function(event) { if (event.type == 'blocking-connection-unstable') { //ah, it's the 'after' phase...we must have the lostPongs shoved into the event var lostPongs = event.lostPongs; //.... //execute the code for submit/after event //.... } }); Now if we want to filter the events as defined by addOnConnectionEventBefore(callback, eventFilter) function we have the "boiler plate" code for filters: function submitBeforefilter(event, callback) { if (event.type == 'submit') { if (event.phase == 'before') { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event); } } } function submitAfterfilter(event, callback) { if (event.type == 'submit') { if (event.phase == 'after') { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event); } } } function blockingConnectionUnstable(event, callback) { if (event.type == 'connection-unstable') { //the callback still needs to do the work of extracting the relevant information from the event structure callback(event) } } So all this work for determining what kind of event is received has to be done in various parts of the component or application code. Oh, but we have the filters to save us from repeating ourselves. But then why do we need to hide the specificity of the event in the first place? Here is the simple version: addOnSubmitSend(function(parameters) { //no need to query for the event type //parameters are available if needed //...execute the code... } ); addOnSubmitResponse(function(responseText, responseXML) { //no need to query for the event type //responseText is available if needed //responseXML is available in case response is in XML format //...execute the code... } ); addOnBlockingConnectionUnstable(function(numberOfReconnectionFailures) { //no need to query for the event type //numberOfReconnectionFailures is available if needed //...execute the code... } );
          Hide
          Mircea Toma added a comment - - edited

          After looking at Mojarra's event notification implementation I could not see a generic after/before event notification pattern. There are only three types of events that can be received: 'send', 'success', and 'complete'.
          I do think though that is better to have separate listener registration for event that have a "before" and "after" phase. This will make it easier for API users to register only for the events they are interested in, since sometimes you care only for the "after" notification and thus avoiding passing a no-operation function as first parameter.
          The list of callback registration functions would look like this:

          function addOnSubmitSend(callback)

          { //... callback(queryParameters); //... }

          function addOnSubmitResponse(callback)

          { //... callback(responseText, responseXML); //... }

          function addOnBeforeDOMUpdate(callback)

          { //... //oldElement might need to have callbacks de-registered callback(oldElement); //... }

          function addOnAfterDOMUpdate(callback)

          { //... //newElement might need callback registered or object instances created callback(newElement); //... }

          function addOnBlockingConnectionUnstable(callback)

          { //... callback(numberOfReconnectionFailures); //... }

          function addOnBlockingConnectionLost(callback)

          { //... callback(numberOfReconnectAttempts); //... }

          function addOnServerError(callback)

          { //... //callback receives the error code and body of the error response callback(errorCode, message); //... }

          function addOnViewDisposal(callback)

          { //... //callback receives the identifier of the view that is about to be disposed callback(viewStateID); //... }

          function addOnSessionExpiry(callback)

          { //... }
          Show
          Mircea Toma added a comment - - edited After looking at Mojarra's event notification implementation I could not see a generic after/before event notification pattern. There are only three types of events that can be received: 'send', 'success', and 'complete'. I do think though that is better to have separate listener registration for event that have a "before" and "after" phase. This will make it easier for API users to register only for the events they are interested in, since sometimes you care only for the "after" notification and thus avoiding passing a no-operation function as first parameter. The list of callback registration functions would look like this: function addOnSubmitSend(callback) { //... callback(queryParameters); //... } function addOnSubmitResponse(callback) { //... callback(responseText, responseXML); //... } function addOnBeforeDOMUpdate(callback) { //... //oldElement might need to have callbacks de-registered callback(oldElement); //... } function addOnAfterDOMUpdate(callback) { //... //newElement might need callback registered or object instances created callback(newElement); //... } function addOnBlockingConnectionUnstable(callback) { //... callback(numberOfReconnectionFailures); //... } function addOnBlockingConnectionLost(callback) { //... callback(numberOfReconnectAttempts); //... } function addOnServerError(callback) { //... //callback receives the error code and body of the error response callback(errorCode, message); //... } function addOnViewDisposal(callback) { //... //callback receives the identifier of the view that is about to be disposed callback(viewStateID); //... } function addOnSessionExpiry(callback) { //... }
          Hide
          Ken Fyten added a comment -

          There is a "big-picture" perspective that we need to keep in mind here, that being that ICEfaces as a whole is targeted at Java developers who do not want/need to become JS experts. Thus, even though we are adding JS APIs I believe that we should lean toward an API approach that will be the most transparent to Java developers with potentially weak JS experience. It does our users no good if we following JS best-practices that they will be unfamiliar with. The ultimate goal is to enable them to be as productive as possible without requiring a bunch of JS experience, best-practices knowledge, etc.

          Having said that, I prefer MIrcea's approach of separate functions for each event type for it's increase in transparency/usability. I do think that we should be able to identify "up front" what the necessary event types should be for something as fundamental as the JS bridge functions. Note that we can revise these through the Alpha/Beta pre-release process as required also. It might make sense to group the connection related functions together via naming, such as OnConnectionError, OnConnectionUnstable (I prefer OnConnectionWarn), etc.

          A few more notes, the "addOnXXX" is horrible. The "add" offers nothing additional in the way of comprehension and serves to muddle up the distinctive parts of each function name, so I vote strongly to lose it entirely. The "onX" pattern is succinct and easily understood by reviewing a few of the function names together, and doesn't get in the way of the unique bits of information about each function.

          For events where having a pre/post event makes sense, how about using pre/post as per normal industry practice: OnDOMUpdatePre() OnDOMUpdatePost. This also has the advantage of putting the tense qualifier at the end of the function name, making related functions group together nicely in a list. It might be better to just have one function with a parameter for Pre/Post, with the default being the most likely case: OnDOMUpdate( Callback) - meaning post, or OnDOMUpdate( "Before", Callback) for pre.

          Show
          Ken Fyten added a comment - There is a "big-picture" perspective that we need to keep in mind here, that being that ICEfaces as a whole is targeted at Java developers who do not want/need to become JS experts. Thus, even though we are adding JS APIs I believe that we should lean toward an API approach that will be the most transparent to Java developers with potentially weak JS experience. It does our users no good if we following JS best-practices that they will be unfamiliar with. The ultimate goal is to enable them to be as productive as possible without requiring a bunch of JS experience, best-practices knowledge, etc. Having said that, I prefer MIrcea's approach of separate functions for each event type for it's increase in transparency/usability. I do think that we should be able to identify "up front" what the necessary event types should be for something as fundamental as the JS bridge functions. Note that we can revise these through the Alpha/Beta pre-release process as required also. It might make sense to group the connection related functions together via naming, such as OnConnectionError, OnConnectionUnstable (I prefer OnConnectionWarn), etc. A few more notes, the "addOnXXX" is horrible. The "add" offers nothing additional in the way of comprehension and serves to muddle up the distinctive parts of each function name, so I vote strongly to lose it entirely. The "onX" pattern is succinct and easily understood by reviewing a few of the function names together, and doesn't get in the way of the unique bits of information about each function. For events where having a pre/post event makes sense, how about using pre/post as per normal industry practice: OnDOMUpdatePre() OnDOMUpdatePost. This also has the advantage of putting the tense qualifier at the end of the function name, making related functions group together nicely in a list. It might be better to just have one function with a parameter for Pre/Post, with the default being the most likely case: OnDOMUpdate( Callback) - meaning post, or OnDOMUpdate( "Before", Callback) for pre.
          Hide
          Mircea Toma added a comment - - edited

          Removed onSessionExpired callback registration. In order to properly invoke this callback Glimmer server-side code should control the session expiry process.
          Instead of relying a special command for session expiry notification the server-side code could send an update notification to all the views when the session is expired. Each view will issue a request for acquiring the corresponding updates but instead of the updates it will receive a session expiry custom error page.

          Show
          Mircea Toma added a comment - - edited Removed onSessionExpired callback registration. In order to properly invoke this callback Glimmer server-side code should control the session expiry process. Instead of relying a special command for session expiry notification the server-side code could send an update notification to all the views when the session is expired. Each view will issue a request for acquiring the corresponding updates but instead of the updates it will receive a session expiry custom error page.
          Hide
          Mircea Toma added a comment - - edited

          Here are the callback registration function that ICEfaces bridge is currently exposing:
          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onServerError(callback-function)

          The registered callback function will be invoked when a server error is received by the browser either on the JSF form submit. The callback function receives the following set of parameters when invoked:

          function callback(statusCode, responseText, responseDOM)

          { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) }
          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onBlockingConnectionServerError(callback-function)

          The registered callback function will be invoked when a server error is received on the blocking connection. The callback function receives the following set of parameters when invoked:

          function callback(statusCode, responseText, responseDOM) { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onBlockingConnectionUnstable(callback-function)

          The registered callback function will be invoked when bridge's hearbeat detects that the server doesn't responds in a timely fashion. The callback function does not receive any parameters when invoked:

          function callback()

          { //no parameters are passed in }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onBlockingConnectionLost(callback-function)

          The registered callback function will be invoked when the blocking connection is lost to the server. The callback function receives the following set of parameters when invoked:

          function callback(reconnectAttempts)

          { //reconnectAttempts - the number of reconnect attempts made by the bridge to re-establish the connection before giving up }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onViewDisposal(callback-function)

          The registered callback function will be invoked when a view within the page is disposed, the view could be a portlet, an include or the whole page. The callback function receives the following set of parameters when invoked:

          function callback(viewID)

          { //viewID - the view ID }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onSubmitSend(callback-function)

          The registered callback function will be invoked when the form submit request is issued. The callback function receives the following set of parameters when invoked:

          function callback(queryParameters)

          { //queryParameters - the query parameters of the request }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onSubmitResponse(callback-function)

          The registered callback function will be invoked when the response corresponding to the form submit is received. The callback function receives the following set of parameters when invoked:

          function callback(statusCode, responseText, responseDOM)

          { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) }

          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onBeforeUpdate(callback-function)

          The registered callback function will be invoked before the updates are to be applied to the DOM. The callback function receives the following set of parameters when invoked:

          function callback(updates)

          { //updates - the updates as defined in the JSF 2.0 javascript specification (see the attached document) }
          ----------------------------------------------------------------------------------------------------------------------------------------------
          ice.onAfterUpdate(callback-function)

          The registered callback function will be invoked before the updates are to be applied to the DOM. The callback function receives the following set of parameters when invoked:

          function callback(updates) { //updates - the updates as defined in the JSF 2.0 javascript specification (see the attached document) }

          ----------------------------------------------------------------------------------------------------------------------------------------------

          Show
          Mircea Toma added a comment - - edited Here are the callback registration function that ICEfaces bridge is currently exposing: ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onServerError(callback-function) The registered callback function will be invoked when a server error is received by the browser either on the JSF form submit. The callback function receives the following set of parameters when invoked: function callback(statusCode, responseText, responseDOM) { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onBlockingConnectionServerError(callback-function) The registered callback function will be invoked when a server error is received on the blocking connection. The callback function receives the following set of parameters when invoked: function callback(statusCode, responseText, responseDOM) { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onBlockingConnectionUnstable(callback-function) The registered callback function will be invoked when bridge's hearbeat detects that the server doesn't responds in a timely fashion. The callback function does not receive any parameters when invoked: function callback() { //no parameters are passed in } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onBlockingConnectionLost(callback-function) The registered callback function will be invoked when the blocking connection is lost to the server. The callback function receives the following set of parameters when invoked: function callback(reconnectAttempts) { //reconnectAttempts - the number of reconnect attempts made by the bridge to re-establish the connection before giving up } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onViewDisposal(callback-function) The registered callback function will be invoked when a view within the page is disposed, the view could be a portlet, an include or the whole page. The callback function receives the following set of parameters when invoked: function callback(viewID) { //viewID - the view ID } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onSubmitSend(callback-function) The registered callback function will be invoked when the form submit request is issued. The callback function receives the following set of parameters when invoked: function callback(queryParameters) { //queryParameters - the query parameters of the request } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onSubmitResponse(callback-function) The registered callback function will be invoked when the response corresponding to the form submit is received. The callback function receives the following set of parameters when invoked: function callback(statusCode, responseText, responseDOM) { //statusCode - the HTTP status code //responseText - the body of the HTTP response in text format //responseDOM - the XML parsed body of the HTTP response (parameter present only when response is in XML/HTML format) } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onBeforeUpdate(callback-function) The registered callback function will be invoked before the updates are to be applied to the DOM. The callback function receives the following set of parameters when invoked: function callback(updates) { //updates - the updates as defined in the JSF 2.0 javascript specification (see the attached document) } ---------------------------------------------------------------------------------------------------------------------------------------------- ice.onAfterUpdate(callback-function) The registered callback function will be invoked before the updates are to be applied to the DOM. The callback function receives the following set of parameters when invoked: function callback(updates) { //updates - the updates as defined in the JSF 2.0 javascript specification (see the attached document) } ----------------------------------------------------------------------------------------------------------------------------------------------
          Hide
          Mircea Toma added a comment -

          document describing the update format

          Show
          Mircea Toma added a comment - document describing the update format
          Hide
          Mircea Toma added a comment -

          Resolving the issue. Future enhancements or changes can go in their own JIRA cases.

          Show
          Mircea Toma added a comment - Resolving the issue. Future enhancements or changes can go in their own JIRA cases.

            People

            • Assignee:
              Unassigned
              Reporter:
              Adnan Durrani
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: