a4j:push sends HEAD-requests forever, is it broken?
tinydragon Dec 17, 2008 6:45 AMIt 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