Are JSF/Primefaces AJAX requests really asynchronous? - ajax

I'm new to JSF so I don't know if the behaviour I'm facing is normal.
I have this code:
<p:selectBooleanCheckbox id="locationChoice1" value="#{login.locationChoice1}">
<p:ajax listener="#{login.chooseLocationType1}" update="locationChoice1 locationChoice2 positionChoice" />
<p:ajax listener="#{login.retrieveGalaxies}" update="test" />
</p:selectBooleanCheckbox>
My login.retrieveGalaxies function has a call to sleep(8000) function to simulate the delay. I expect my componenents locationChoice1, locationChoice2 and positionChoice to be updated in 1 or 2 seconds and my test component to be updated in 8 secondes but all are updates in 8 seconds.
Is this the correct behaviour?
I tried to play with async parameter but it didn't change the result.

They're really asynchronous (JS context isn't blocked; i.e. you can run other arbitrary JS code at the same moment without being blocked). The behaviour you're seeing is because they're queued. So it look like as if they are not asynchronous.
This queueing behaviour is specified in chapter 13.3.2 of the JSF 2 specification:
13.3.2 Ajax Request Queueing
All Ajax requests must be put into a client side request queue before they are sent to the
server to ensure Ajax requests are processed in the order they are sent. The request that has been waiting in the queue the
longest is the next request to be sent. After a request is sent, the Ajax request callback function must remove the request
from the queue (also known as dequeuing). If the request completed successfully, it must be removed from the queue. If
there was an error, the client must be notified, but the request must still be removed from the queue so the next request
can be sent. The next request (the oldest request in the queue) must be sent. Refer to the jsf.ajax.request
JavaScript documentation for more specifics about the Ajax request queue.
This is done so to ensure integrity and threadsafety of the JSF view state (and inherently thus also view scoped beans).

Related

Handling concurrent call to conversational components on JBoss Seam

I'm working on a project using JBoss Seam 2.2.6, JSF 1.2 and RichFaces 3.
Users of the application must enter data in a form, and for certain fields it is necessary to make calls to the backend to recalculate other values ​​based on the data entered.
Back-end calls are made using the AJAX support RichFaces offers, for example, using <a4j: support> for onchange events.
This is the Jsf/RichFaces code:
<h:selectOneMenu value="#{managedBean.someValue}" >
<s:selectItems value="#{managedBean.entityList}" var="_item"
label="#{_item.label}"
itemValue="{item.value}"
/>
<a4j:support
event="onchange" // handling onchange event
status="waitStatus" // "please wait.." pop up blocks UI
eventsQueue="afjQueue" // ajax requests queue
ignoreDupResposes="true" // avoid similar requests
action="#{managedBean.onInputChange()}"
reRender="somePanel"
oncomplete="showErrors();"
/>
</h:selectOneMenu>
The problem is that the user could click on different fields of the form or on different buttons, make multiple requests to the server in a short period of time, and Seam does not support concurrent calls to the same conversation scoped component (if it happened a ConcurrentCallToConversation error would occur )
To avoid this we have done the following:
1) adding a a4j:queue for queueing AJAX requests
2) setting ignoreDupResposes="true" to avoid "similar" requests.
3) setting seam core property concurrent-request-timeout="5000" (info about this property. This property causes a request to have exclusive control of the component for 5 seconds)
4) adding a a4j:status that shows a "please wait..." dialog between request starts and request ends, blocking the UI
Because the user experience is affected by a pop up that appears every time an ajax request is made, i want to delete the alternative 4.
So my question is: Is it guaranteed that there will not occur a concurrent call to conversation if I use a queue of requests and a large enough timeout for exclusive access? meaning that using the first 3 items would be enough.

Deleting from ajax queue backbone

I've implemented the backbone ajax queue as mentioned here Ajax queue Backbone js
Now I would like to clear pending queued ajax requests in the pipe. How to do that?
For example:
I've 1 backbone save which has not yet returned from the server and is processing. And one more backbone save is in the queue. Now if a third backbone save call comes, the one in the queue (2nd backbone save) should get removed and ignored. It should not call the server and the third one should get processed once the first backbone save returns.

ajax request per div

I have 10 divs on my page and each div will render its own ajax request when the page loads. I know i can make max 2 ajax requests and then i have to wait (based on the browser) before the next request gets fired. I was wondering what will be the best way to design such a page.
Should i create ajax request inside the divs so that i can pass the div as a context to the ajax reponse? something like this:
<div id="request1">
make an ajax request
</div>
<div id="request2">
make an ajax request
</div>
and so on......
is there any chance that result may get mixed up and wrong div will render the result from the different request?
--Edit--
I cannot make a single call as they all make calls to separate service and that service may or may not be available.
AJAX is Asynchronous, that way, if you call 10 AJAX requests using either $.get, $.post or $.ajax, those requests will fire independently without waiting for the previous ones. So unless you have a special requirements that need to avoid that, just go ahead
Why don't you send only one ajax request when the page loads, and let your server side script return the data needed for the 10 divs in form of json? That would reduce the number of requests sent to the server and the work would be a lot cleaner as well.
Edit : ok since this is no longer and option. You can queue the requests one after another, if each request you are sending, depends on each other (for eg: you might set a flag in the first request, which again gets check in a later request) you can queue them. I have been using this plugin for quite a while now, and it has come in handy)
You might be able to use in your case so check it out.
http://www.protofunc.com/scripts/jquery/ajaxManager/

ExtJS 4 - How to check if all current ajax requests are completed and then perform an action?

I have a page which fires Ajax requests for validations at server side. I need to perform an action when all the ajax requests have finished loading or are completed.
For this, I am using Ext.Ajax.isLoading() in a recursive function in following way:
function chechValid(){
if(Ext.Ajax.isLoading()){
checkValid();
}else{
//Code for Action 1
}
}//EOF
checkValid();
//Code for Action 2
The problem is that when I do this, browsers give the following errors:
Mozill FF - too much recursions
IE - Stack overflow at line:18134
If this recursion is a heavy thing for the browsers, then how to perform a task when all the Ajax requests have finished loading?
Using delay is not what I want as, if delay is used then browser begins executing the other code (like 'Code for Action 2' as shared above) which is not what is expected.
The main aim is that the browser shouldn't execute anything unless all the Ajax requests are complete and once completed then it should perform a particular action.
Any suggestions/help on this one?
Thanks in Advance.
PS: Using ExtJs 4.0.7
(Updated)More Detail about the actual situation:-
Here is brief description of the situtaion being faced - There is a form, in which I need to perform server side validations on various fields. I am doing so by firing an ajax request on blur event. Depending upon the server response of validation Ajax fired on blur, fields are marked invalid and form submission is not allowed. (Avoiding 'change' event as that causes alot of overhead on server due to high number of Ajas requests and also leads to fluctuating effects on a field when response from various such Ajax requests are received).
Things are working fine except in one case - when user modifies the value of a field and instead of 'tab'bing out from the field she directly clicks at the save button. In such a case, though, the blur event gets fired but the processing of 'Save' doesn't wait for Ajax Validation response and submits the form. Thus, I somehow need to check if Ajax requests have finihed loading and the process the saving of form. requestComplete would unfortunately not serve the purpose here. And if try using the recursion, then of course, the browser is hung due to high usage of resources. Same case occurs if I try using a pause script work around ( as shared here - Javascript Sleep).
Any possible workaround for this one?
TIA
Your method will lead to infinite recursion.
A better way is to register a callback function in Ext.Ajax.requestcomplete, something like this (not tested):
Ext.Ajax.on('requestcomplete', function(conn, response, options) {
if (!Ext.Ajax.isLoading()) {
//your action...
}
}
};
Unless I am misunderstanding the issue couldn't you create a couple of globals. I know globals are bad, but in this case it will save you quite a bit of headache. One global would be "formReady" and initially set it to false, the other would be "ajaxActive" and set to false. You would also add an onSubmit method that would validate that "formReady" was true and if not alert the user that validation was occurring (or you could set a timeout for form submission again and have a second validation that checks to see if "ajaxActive" is true). When the AJAX call is made it would set the variable "ajaxActive" to true and once complete would set formReady to true. You could also potentially resubmit the form automatically if the response from the AJAX was that the form was good.
Ext.Ajax.request() returns a transaction object when you call it, which is unique and allows you to recognise and abort specific Ajax requests.
By just calling Ext.Ajax.isLoading() without a specified transaction object, it defaults to the last request, which is why you have to call it recursively at the moment.
If it were me, I'd create an array of these transaction objects as you fire them off, and pass each of those in as optional parameters to the Ext.Ajax.isLoading() function to check if a particular request has finished. If it has, you can remove that transaction object from the array, and only progress with the save when your array is empty.
This would get round your recursion problem, since you've always got a finite number of requests that you're waiting on.
if (Object.keys(Ext.Ajax.requests).length === 0) console.log("No active requests");

Prototype.js, AJAX form submission occasionally returns status 0, XHR stays in readyState 1

I've got an odd problem here with Prototype 1.7.0 and an AJAX form submission using form.request().
The response status is either 202 or 200 depending on whether the server expects to be polled again with the same form submission after a timeout. 200 indicates that the response contents are done and are to be displayed to the user (backend uses WebWork's execAndWait-interceptor to execute a long-running job).
The problem is that most of the time, everything works just fine. However, occasionally, the response comes back as status code 0 and XMLHTTPRequest readyState 1. Firebug indicates correct response codes are coming from the backend, and that the actual response contents are fine, it's just that Prototype's on200 and on202 handlers do not fire (on0 does).
It appears there are similar issues reported over the Internet, but there is no conclusive solution. Is this some well known problem?
A response code 0 from prototype means that it can't communicate with the server. You can remedy this by adding an "on0: function() {}" event handler in your request.
How you handle it is up to you...either alert the user that something went wrong, and redisplay their form, or silently try and re-submit your request to the backend in a loop. If you choose the second option, set a wait timeout and each time you can't talk to the server multiply it by some factor so you don't infinite loop their browser.
You might also want to look into queuing these requests on the client-side so you're only firing one at a time, in order.
Hope that helps.

Resources