3 Replies Latest reply on Dec 18, 2008 10:08 AM by tinydragon

    a4j:push sends HEAD-requests forever, is it broken?

    tinydragon

      It seems that the a4j:push component is somewhat broken. It doesn't stop sending head-requests to the server even if it is not enabled anymore and rerendered.
      I've used a Firefox plugin to monitor all sended requests to determine that.

      Lets take a look at a4j:push example in the 3.22 GA demo applikation. It is facing the same problems. If you press start, the a4j:push component is activated and head requests are send to the server. If you press stop, it is rerended as disabled (enabled attribute=false) but the head request sending doesn't stop. They're send forever.

      After a bit of investigation i stumbled upon the following functions in the JSFAJAX.js library:

      A4J.AJAX.Push
      A4J.AJAX.StopPush

      They are responsible for the client side handling of the polling stuff for the a4j:push component. After a closer look i think that the "Push" function is somewhat broken.

      A4J.AJAX.Push = function( containerId, form, options ) {
       A4J.AJAX.StopPush(options.pushId);
       options.onerror = function(){
       // For error, re-submit request.
       A4J.AJAX.Push(containerId,form,options);
       };
       A4J.AJAX._pollers[options.pushId] = window.setTimeout(function(){
       var request = new XMLHttpRequest();
       request.onreadystatechange = function(){
       if (request.readyState == 4 ) {
       try {
       if(request.status == 200){
       if(request.getResponseHeader("Ajax-Push-Status")=="READY"){
       A4J.AJAX.SubmitRequest(containerId,form||options.dummyForm,null,options);
       }
       }
       } catch(e){
       // Network error.
       }
       // Clear variables.
       request=null;
      
       A4J.AJAX._pollers[options.pushId] = null; // WHY NEEDED? MAY PREVENT StopPush LATER?
       // Re-send request.
       A4J.AJAX.Push( containerId, form, options ); // THIS LINE CAUSES THE INFINITE LOOP
       }
       }
       A4J.AJAX.SendPush( request,options );
       },options.pushinterval);
      };
      


      The function calls itself over and over again even if it gets and 200 with a propper Ajax-Push-Status HTTP header because of the last line in the onreadystate function.

      I've patched this function a little and it works now. The sended requests (POST, HEAD, HEAD, HEAD... POST) are in the right order now.

      A4J.AJAX.Push = function( containerId, form, options ) {
       A4J.AJAX.StopPush(options.pushId);
       options.onerror = function(){
       // For error, re-submit request.
       A4J.AJAX.Push(containerId,form,options);
       };
       A4J.AJAX._pollers[options.pushId] = window.setTimeout(function(){
       var request = new XMLHttpRequest();
       request.onreadystatechange = function(){
       if (request.readyState == 4 ) {
       try {
       if(request.status == 200){
       if(request.getResponseHeader("Ajax-Push-Status")=="READY"){
       A4J.AJAX.SubmitRequest(containerId,form||options.dummyForm,null,options);
       }
       }
       else
       {
       // Re-send request.
       A4J.AJAX.Push( containerId, form, options );
       }
       } catch(e){
       // Network error.
       }
       // Clear variables.
       request=null;
       }
       }
       A4J.AJAX.SendPush( request,options );
       },options.pushinterval);
      };
      


      Is this really a bug or only a misuse? Can i patch this function in that way?


      We use:

      - JBoss 4.2.2 GA
      - JSF Reference Implementation 1.2.09 b2
      - Seam 2.0.2 SP1
      - Richfaces 3.2.2 GA
      - Facelets 1.1.14

        • 1. Re: a4j:push sends HEAD-requests forever, is it broken?
          ilya_shaikovsky

          checked the demo online and on local 3.3.0 build. In firebug I can't see that requests still sent after push stoped. Head request stoped for me after stop button.

          • 2. Re: a4j:push sends HEAD-requests forever, is it broken?
            tinydragon

            That is somewhat weird. I used the HttpFox Plugin for testing.

            I've tested it again with HttpFox against the online demo some minutes ago and it still happens to me. I've made some tests, and i don't understand the results:

            FF3 with Firebug -> stops
            FF3 with HttpFox -> send forever
            FF2 with Firebug -> send forever
            IE7 with Http Watch professional -> send forever
            Fiddler (local http proxy) -> send forever sometimes, but not always

            You have to wait a bit (10 seconds or so) before you press stop. I pressed stop 2 seconds after a post (get new GUID from server) happens.

            During development, i've debugged the two AJAX core functions , Push and StopPush, with Firebug to understand the functionality. While debugging, everything works fine. Buf after switching off Firebug, and testing without debugging, it happens again.

            Seems like a kind of race condition. Do you have any idear?

            • 3. Re: a4j:push sends HEAD-requests forever, is it broken?
              tinydragon

              We use a4j:push not in that way it is used in the demo application with start and stop buttons. We trigger an action with an a4j:commandLink and use a4j:push to wait for an asyn answer from the server. If the js polling thing gets his READY header, the surround form is submitted again to fulfil the whole jsf lifecycle. During that cycle, we set the enabled property of the a4j:push component to false. It is rerendered after the cycle and the poller should be stopped because of the deliverer client side js code. But it isn't.

              Maybe that's producing the race condition because we have not "exclusive" stop button.