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.
Related
I have a small university project in which I have to show how certain algorithms work. Decided to use JSF for a simple webapp and save all the algorithm generated data into a database.
I thought to myself 'hey, it would be cool if I can show the user how the algorithm works step by step, nothing fancy, just plain formatted text that changes when the algorithm does its thing. An output text field with Ajax should get the work done!', but I can't quite get my head around a certain problem. Ajax triggers when a certain event occurs, like 'click' or 'keyup', but is there a way to make it trigger when an object in my ManagedBean class changes?
Don't know if I explained well enough, so here's an example of what I want to do:
An ArrayList in the ManagedBean is empty, the outputtext prints out nothing
After a certain amount of time, a new object is saved in the ArrayList, Ajax triggers and the outputtext prints out its onString()
After a certain amount of time again, the same object that was printed out before changes, Ajax triggers and the outputtext changes accordingly
I'm sorry if the problem isn't quite clear, tried describing it to the best of my ability.
What you describe isn't classic, client-triggered AJAX anymore but known as server-sent events (SSE). They're usually implemented using long-polling (periodic client requests that only get an answer if there's a server-side event).
Your favorite JSF toolkit probably supports it under the name "Push". Here's a Primefaces example.
However, for your simple use case I'd suggest using polling instead. See this example. The main difference is that your server side logic switches to keep a list of "to be displayed" strings/ids/objects. When your browser client polls the server (the listener method gets called), assign the first item to a String field in a backing bean and have your client re-render an area where this String is shown.
Note that you can do this in plain JSF-2, there's no need for Primefaces.
I am trying to use portlets based on MVCPortlet on Liferay 6.1.1, and it does not behave as I was expecting. My portlets are supposed to be independent, but are not...
My need:
I have a first portlet A with a form.
I have several instances of a portlet B, based on MVCPortlet.
When the form is submitted, the portlet A launches an event, and all portlet B receive this event. When a portlet B receive the event, it must build an URL, connect to it and read data from it, and display the result.
My B portlet is based on MVCPortlet, is instanceable, ajaxable and with a render-weight of 0, for having a parallel processing and displaying of all instances of portlet B.
But it does not work well:
1) I could not do the processing of the URL in the event processing, as all events reception (one per instance of my portlet B ) are processed in the same thread. So in the event I just set a renderRequest parameter, so the jsp page automatically use an ActionURL to call the action processing in my portlet.
This action builds the URL, use it, process the data, and redirect to the result display page (response.setRenderParameter("jspPage", "/html/display/results.jsp")).
2) I was expecting each portlet to be independent from the other, but they are not. There is only one instance of the MVCPortlet, shared by all portlets, that greatly surprised me. The portlet session is also shared by all my instances of portlet. The action method is executed by different thread, that is good, but the rendering of portlets can be blocked by actions processing of other portlets. One portlet can provoke the whole page refresh. All things that I wanted to avoid by having instanceable, ajaxable and render-weight with 0...
I wonder if there is something wrong, if it is normal to have only one instance of the class extending MVCPortlet, etc. Or if there is a best way to have the desired behavior.
1) I'm not completely sure what you're doing here: Event handling is AFAIK undefined in terms of parallelism, so it's normal behaviour that all events are handled sequentially in the same thread. However, I don't understand what you mean by the ActionURL part of your description. You're able to change state of your portlet in the eventhandler, but not during the render phase. Typically every request handles only one action, multiple (as necessary) events, then renders all portlets. Do you imply that this is followed by an action on every single B-portlet? That's unexpected and I'd rather recommend you do either the processing in your event handler or trigger it to asynchronously run in the back while continuing through the event processing (especially when it takes time)
2) The portlets are independent of each other, however, not every portlet maps to a single Java object. In fact, the implementation is just like in the servlet world: There's only one object that's not supposed to have any state. Almost all instances of member variables in a portlet (or a servlet) are a sign of misunderstanding the API: The whole state of the portlet is coming in through the various PortletRequest and PortletResponse objects, nothing shall be kept within portlet member variables.
Based on your intent to asynchronously render all B portlets, I assume that rendering might take a while - eventhandling should continue as quickly as possible. Otherwise there's no point in rendering asynchronously if the whole result is already there.
I'm currently developing a JSF application with single-page-per-app design, such like in desktop apps. the sections are placed in tabs, and every suboperation, such as editing or inserting item, in displayed in dialog.
What is becoming the issue, it is both the size of ViewState and the processing time of each request. At the moment, the initial size of ViewState in POST is 200kb (and the compression is enabled). The request last from 200 to 400 ms (on my own machine, with no users except me).
Setting state saving to session greatly reduces the request, but greatly increases the processing time - now it's from 350 to 600 ms. Because this is intranet application, net transfer is cheap, so better to send more that process longer.
I don't know how to deal with that problem. Is it possible to reduce the space consumed by JSF components? Most of them don't change on every click, but they seem to be deserialized and processed anyway. Or should I throw out every data (such as dictionaries for drop-down lists) from JSF beans and use intensive caching in service layer? Or there are other options/tricks/improvements I could use?
As you have already figured out, the View State of the entire form is being serialized on every ansynchronous post back so that the server and client can stay in sync. ASP.NET works in pretty much the exact same way.
The Primefaces team has added functionality to many of their Ajax enabled components that allow for Partial Page posts.
http://blog.primefaces.org/?p=1842
The partialSubmit property will only serialize form elements that are specified in the process attribute of the component or <p:ajax>. Of course this is only a solution for Primefaces components, but it has significantly reduced the request size on some of my larger JSF pages.
You can utilize IFrames and session variables to reduce component trees. Each iframe will maintains its own view. Of course in back end process your application is no longer a single page application. However user will still seamlessly see it as a single age applications.
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).
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");