ICEfaces
  1. ICEfaces
  2. ICE-9626

Processing of asynchronous push starts before browser DOM update has finished

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: EE-3.3.0.GA_P01
    • Fix Version/s: 4.0.BETA, EE-3.3.0.GA_P02, 4.0
    • Component/s: Bridge, Framework
    • Labels:
      None
    • Environment:
      All, ICEpush
    • Assignee Priority:
      P2
    • Salesforce Case Reference:

      Description

      When navigating to a new JSF view with a big DOM and the backing bean of the view being navigated to triggers an asynchronous render as part of its postConstruct or as part as one of the getters, the HTTP POST to retrieve the updates for this asynchronous render posts to the old view instead of the new view and this causes a "Server Internal Error" because of a javax.faces.FacesException being thrown.

      In testing I did find that I wasn't able to reproduce the issue with lazyPush=true, but this may just be workaround for the test case only as it seems to occur when the push connection is already active.
      1. bigdom.xhtml
        499 kB
        Ted Goddard
      2. Case12432Example.zip
        24 kB
        Arran Mccullough
      3. newbigdom.xhtml
        499 kB
        Leon Steffens
      4. NewPageBean.java
        1 kB
        Leon Steffens
      5. PageBean.java
        1 kB
        Ted Goddard
      6. pushdelay.patch
        2 kB
        Ted Goddard

        Activity

        Hide
        Arran Mccullough added a comment -

        Attached test case that reproduces the issue. Note: for the war file the icefaces-ace and icefaces-compat jars need to be added back in.

        Steps:
        When clicking on the "Go to small DOM" link the navigation to the new view completes successfully and the async render is pushed to the new view. When clicking the "Go to big DOM" link the server error will be observed.

        Show
        Arran Mccullough added a comment - Attached test case that reproduces the issue. Note: for the war file the icefaces-ace and icefaces-compat jars need to be added back in. Steps: When clicking on the "Go to small DOM" link the navigation to the new view completes successfully and the async render is pushed to the new view. When clicking the "Go to big DOM" link the server error will be observed.
        Hide
        Ted Goddard added a comment -

        Have they tried an application-level workaround where they just delay the push?

        Show
        Ted Goddard added a comment - Have they tried an application-level workaround where they just delay the push?
        Hide
        Arran Mccullough added a comment -

        They do have a Thread.sleep(50); in the attached test case. But how would they be able to know once the DOM has finished loading to determine the right delay to use?

        Show
        Arran Mccullough added a comment - They do have a Thread.sleep(50); in the attached test case. But how would they be able to know once the DOM has finished loading to determine the right delay to use?
        Hide
        Ted Goddard added a comment -

        Modified PageBean and bigdom.xhtml that initiate push only once page is rendered.

        Show
        Ted Goddard added a comment - Modified PageBean and bigdom.xhtml that initiate push only once page is rendered.
        Hide
        Ted Goddard added a comment -

        ICEpush also does not know when rendering of the page has completed. A modified bean and bigdom page have been attached that make use of a PhaseListener to initiate the push only when the page is completely rendered. For the actual application, it may be necessary to use the PhaseListener in combination with the actual event that triggers the push so that the push will be triggered then delayed until the page is ready.

        Show
        Ted Goddard added a comment - ICEpush also does not know when rendering of the page has completed. A modified bean and bigdom page have been attached that make use of a PhaseListener to initiate the push only when the page is completely rendered. For the actual application, it may be necessary to use the PhaseListener in combination with the actual event that triggers the push so that the push will be triggered then delayed until the page is ready.
        Hide
        Leon Steffens added a comment -

        I've tried this workaround and it works sometimes but it's not 100% reliable. By clicking the Big DOM link, refreshing, clicking the link, Refreshing, etc. I can reproduce the problem about half of the time. The problem is still that the PhaseListener executes (so the async push is triggered) after the JSF view has been rendered, but before the DOM has been updated in the browser. The retrieveUpdate(view) function in application.js then tries to get the retrieve-update form for the view but it's getting the old form:

        <form action="/iceasync/welcome.jsf" id="vlktwhjc-retrieve-update" method="post" name="vlktwhjc-retrieve-update">

        instead of the new one:
        <form action="/iceasync/bigdom.jsf" id="vlktwhjc-retrieve-update" method="post" name="vlktwhjc-retrieve-update">

        and this causes the actual HTTP POST to retrieve the updates to be posted to /iceasync/welcome.jsf instead of /iceasync/bigdom.jsf. In ICEfaces 1.8.2 this POST was made to /iceasync/block/receive-updates and the view ID was passed in as a parameter, so this problem did not exist.

        I don't think this problem can be solved on the server-side (without adding some artificial delay) - the only way I can work around this problem is to add some Javascript to the end of the resulting DOM to notify the server that the DOM has been updated and the async push can be triggered. I have attached the new versions of the bigdom.xhtml and PageBean. Using this workaround the everything works fine but it causes an extra HTTP POST to notify the server that we are ready to receive the async push. As we are using async pushes extensively this will drastically increase the traffic between the browser and the server and I don't think it's an acceptable workaround.

        Show
        Leon Steffens added a comment - I've tried this workaround and it works sometimes but it's not 100% reliable. By clicking the Big DOM link, refreshing, clicking the link, Refreshing, etc. I can reproduce the problem about half of the time. The problem is still that the PhaseListener executes (so the async push is triggered) after the JSF view has been rendered, but before the DOM has been updated in the browser. The retrieveUpdate(view) function in application.js then tries to get the retrieve-update form for the view but it's getting the old form: <form action="/iceasync/welcome.jsf" id="vlktwhjc-retrieve-update" method="post" name="vlktwhjc-retrieve-update"> instead of the new one: <form action="/iceasync/bigdom.jsf" id="vlktwhjc-retrieve-update" method="post" name="vlktwhjc-retrieve-update"> and this causes the actual HTTP POST to retrieve the updates to be posted to /iceasync/welcome.jsf instead of /iceasync/bigdom.jsf. In ICEfaces 1.8.2 this POST was made to /iceasync/block/receive-updates and the view ID was passed in as a parameter, so this problem did not exist. I don't think this problem can be solved on the server-side (without adding some artificial delay) - the only way I can work around this problem is to add some Javascript to the end of the resulting DOM to notify the server that the DOM has been updated and the async push can be triggered. I have attached the new versions of the bigdom.xhtml and PageBean. Using this workaround the everything works fine but it causes an extra HTTP POST to notify the server that we are ready to receive the async push. As we are using async pushes extensively this will drastically increase the traffic between the browser and the server and I don't think it's an acceptable workaround.
        Hide
        Leon Steffens added a comment - - edited

        Attached new versions of files showing Javascript workaround.

        Show
        Leon Steffens added a comment - - edited Attached new versions of files showing Javascript workaround.
        Hide
        Ted Goddard added a comment -

        Please explain a use case in the application – perhaps there is a characteristic to the page update or the trigger of the push that will indicate a better workaround.

        Show
        Ted Goddard added a comment - Please explain a use case in the application – perhaps there is a characteristic to the page update or the trigger of the push that will indicate a better workaround.
        Hide
        Ted Goddard added a comment -

        JavaScript patch for delaying push when a user event is in progress.

        Show
        Ted Goddard added a comment - JavaScript patch for delaying push when a user event is in progress.
        Hide
        Ted Goddard added a comment -

        icefaces.jar with patch applied

        Show
        Ted Goddard added a comment - icefaces.jar with patch applied
        Hide
        Ted Goddard added a comment -

        The sequence of events in the test case are as follows:

        • user clicks on commandLink, ajax event begins
        • page is rendered on server
        • push event occurs
        • browser handles push event, attempts to update welcome page since that is the action on the current form
        • commandLink click event completes
        • push updates are applied resulting either in error or return to welcome page

        The patch detects an outstanding ajax event and delays the retrieval of push updates until the ajax event is complete.

        After additional testing, this will be considered for a fix in the ICEfaces trunk.

        Show
        Ted Goddard added a comment - The sequence of events in the test case are as follows: user clicks on commandLink, ajax event begins page is rendered on server push event occurs browser handles push event, attempts to update welcome page since that is the action on the current form commandLink click event completes push updates are applied resulting either in error or return to welcome page The patch detects an outstanding ajax event and delays the retrieval of push updates until the ajax event is complete. After additional testing, this will be considered for a fix in the ICEfaces trunk.
        Hide
        Leon Steffens added a comment -

        Thank you very much Ted. I have applied the patch and removed our workaround and everything seems to be working great! We will continue with the testing on our side but as far as I can tell the issue is fixed.

        Show
        Leon Steffens added a comment - Thank you very much Ted. I have applied the patch and removed our workaround and everything seems to be working great! We will continue with the testing on our side but as far as I can tell the issue is fixed.
        Hide
        Ted Goddard added a comment -

        Change is checked in to ICEfaces 3 trunk.

        Show
        Ted Goddard added a comment - Change is checked in to ICEfaces 3 trunk.
        Hide
        Ted Goddard added a comment -

        Backport applied. Some surrounding code was changed, so some adjustment was required. Push updates verified working in auction and showcase.

        Show
        Ted Goddard added a comment - Backport applied. Some surrounding code was changed, so some adjustment was required. Push updates verified working in auction and showcase.

          People

          • Assignee:
            Ted Goddard
            Reporter:
            Arran Mccullough
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: