Im currently trying out the ajax feature, and im curious about how can i display the error messages occured when i do the ajax stuff ?
For example, i have a primefaces button :
<p:commandButton value="Refresh" update="debugPanel messages"
action="#{checkbocLabBean.submit}"/>
When testing that button, nothing seems to happen, until i check the server logs, there's an exception. It turns out that i have a typo. Should be #{checkboxLabBean.submit}.
The only thing i can think of right now is to have disable the ajax, adding ajax="false" in my case, and the error will show up.
Is there any other ways to show errors right into the browser in development phase when using ajax requests ?
Ajax requests happens asynchronously. They do by default not affect the entire document. Exceptions thrown during PrimeFaces' ajax requests are delegated to <p:ajaxStatus>. You can do your thing in <facet name="error">.
<p:ajaxStatus>
<f:facet name="start">Loading...</f:facet>
<f:facet name="success"><h:outputText value="" /></f:facet>
<f:facet name="error">An error has occurred!</f:facet>
</p:ajaxStatus>
If you rather want to replace the current document with the error page -which is a very reasonable choice- then it's good to know that PrimeFaces uses jQuery under the covers and that you can configure jQuery as follows to do so:
<script>
jQuery.ajaxSetup({
error: handleXhrError
});
function handleXhrError(xhr) {
document.open();
document.write(xhr.responseText);
document.close();
}
</script>
See also:
How to safeguard webapplication on server-side errors?
Handling of server-side HTTP errors in jQuery's ajax requests
Related
I have a datatable in which the first column contains some links to display the details for each item. I am using f:ajax to send the request to the action listener.
While it does work for the first time (when I click the first link or any link) but after that it stops working and no request is sent to the actionlistener.
<h:commandLink value="#{inquiry.myObject.property}"
actionListener="#{myBean.getDetail}">
<f:param name="someName" value="#{someBean.someName}"/>
<f:ajax
render=":#{p:component('infoDisplay')}
:#{p:component('addFieldSet')} :#{p:component('myDetailsId')}" />
</h:commandLink>
How do I make sure that the request is generated for every link and not just for the first attempt ?
UPDATE---
here is the action listener
public void getDetail(ActionEvent event) {
String xyz=context.getRequestParameterMap().get("someName").toString();
//some task
}
I have set a breakpoint on the first line of this function. This function gets called only once (for the first time).
After the first successful ajax call, I can see the below error in developer tools.
customer?p_p_id=account_WAR_XXX&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_cacheability=cacheLevelPage&p_p_col_id=column-1&p_p_col_count=6&p_p_col_pos=1&_account_WAR_XXX_javax.faces.resource=primefaces.js&_account_WAR_XXX_ln=primefaces&v=4.0:5 Uncaught TypeError: Cannot read property 'source' of undefined
replaced <f:ajax render> with <p:ajax update>. I no longer see the javascript bug on the developer tools and all the functionality seems to work as expected.
I have added ui:include and now some ajax events within the included page are not firing.
Some ajax calls are working, but specifically the update on pe:inputNumber is not:
<pe:inputNumber value="#{trans.toBeAllocatedAmount}"
<p:ajax listener="#{bankBean.updateAllocatedTotal()}"
update="tblReceipts" />
</pe:inputNumber>
is not firing any ajax calls.
If I put the page in directly instead of an include it works.
I have PF5 and PE2
Any ideas or suggestions as to what the issue could be?
I have rolled it back and it appears to be PF5 related.
My code in RichFaces 3.3.3:
<a:region>
<h:form>
<a:poll id="feed" enabled="true" reRender="feedReader" interval="100"/>
</h:form>
</a:region>
<h:form>
<h:outputText value="#{feedReader2.title}" id="feedReader" />
</h:form>
This is close to the example here: http://www.mastertheboss.com/richfaces/using-ajax-with-jboss-richfaces
What it should do is poll the server which reads an rss feed and gives back the title.
However, this is not working. In Chrome developer tools I can't see any AJAX requests made to the server. Instead, I see an error Uncaught TypeError: Cannot read property action of null on framework.pack.js. The line in which the error occurs is:
this._actionUrl=(this._form.action)?this._form.action:this._form
I can only guess that this is releated to the <h:form> which doesn't have an action attribute. But I don't see why I need this here, as it is not included in all of the examples you can find.
Moreover, I do not want the <h:outputText> to query the bean on page load. My aim is to use AJAX to read the feed after the page is done rendering.
If this is an issue related to my RichFaces version, could someone please give me an example on how to do this in 3.3.3?
I found the issue. It was an error outside the above markup i've included. Had two <h:form> nested, which caused the second one to malfunction.
I am trying to execute a JSF2 bean method and show a dialog box after completion of the method on click of PrimeFaces <p:commandButton>.
<p:commandButton id="viewButton" value="View"
actionlistener="#{userBean.setResultsForSelectedRow}" ajax="false"
update=":selectedRowValues"
oncomplete="PF('selectedRowValuesDlg').show()">
</p:commandButton>
<p:dialog id="selectedRowValues" widgetVar="selectedRowValuesDlg" dynamic="true">
<h:outputText value="#{userBean.selectedGroupName}" />
</p:dialog>
When I click on the command button, the bean action listener method setResultsForSelectedRow executes properly, but it does not show the dialog box when the method completes. If I remove actionlistener, it shows the dialog box. I do not know what is going wrong.
What is the execution order of events? Is it possible to execute actionlistener and oncomplete simultaneously?
It failed because you used ajax="false". This fires a full synchronous request which in turn causes a full page reload, causing the oncomplete to be never fired (note that all other ajax-related attributes like process, onstart, onsuccess, onerror and update are also never fired).
That it worked when you removed actionListener is also impossible. It should have failed the same way. Perhaps you also removed ajax="false" along it without actually understanding what you were doing. Removing ajax="false" should indeed achieve the desired requirement.
Also is it possible to execute actionlistener and oncomplete simultaneously?
No. The script can only be fired before or after the action listener. You can use onclick to fire the script at the moment of the click. You can use onstart to fire the script at the moment the ajax request is about to be sent. But they will never exactly simultaneously be fired. The sequence is as follows:
User clicks button in client
onclick JavaScript code is executed
JavaScript prepares ajax request based on process and current HTML DOM tree
onstart JavaScript code is executed
JavaScript sends ajax request from client to server
JSF retrieves ajax request
JSF processes the request lifecycle on JSF component tree based on process
actionListener JSF backing bean method is executed
action JSF backing bean method is executed
JSF prepares ajax response based on update and current JSF component tree
JSF sends ajax response from server to client
JavaScript retrieves ajax response
if HTTP response status is 200, onsuccess JavaScript code is executed
else if HTTP response status is 500, onerror JavaScript code is executed
JavaScript performs update based on ajax response and current HTML DOM tree
oncomplete JavaScript code is executed
Note that the update is performed after actionListener, so if you were using onclick or onstart to show the dialog, then it may still show old content instead of updated content, which is poor for user experience. You'd then better use oncomplete instead to show the dialog. Also note that you'd better use action instead of actionListener when you intend to execute a business action.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
Differences between action and actionListener
I just love getting information like BalusC gives here - and he is kind enough to help SO many people with such GOOD information that I regard his words as gospel, but I was not able to use that order of events to solve this same kind of timing issue in my project. Since BalusC put a great general reference here that I even bookmarked, I thought I would donate my solution for some advanced timing issues in the same place since it does solve the original poster's timing issues as well. I hope this code helps someone:
<p:pickList id="formPickList"
value="#{mediaDetail.availableMedia}"
converter="MediaPicklistConverter"
widgetVar="formsPicklistWidget"
var="mediaFiles"
itemLabel="#{mediaFiles.mediaTitle}"
itemValue="#{mediaFiles}" >
<f:facet name="sourceCaption">Available Media</f:facet>
<f:facet name="targetCaption">Chosen Media</f:facet>
</p:pickList>
<p:commandButton id="viewStream_btn"
value="Stream chosen media"
icon="fa fa-download"
ajax="true"
action="#{mediaDetail.prepareStreams}"
update=":streamDialogPanel"
oncomplete="PF('streamingDialog').show()"
styleClass="ui-priority-primary"
style="margin-top:5px" >
<p:ajax process="formPickList" />
</p:commandButton>
The dialog is at the top of the XHTML outside this form and it has a form of its own embedded in the dialog along with a datatable which holds additional commands for streaming the media that all needed to be primed and ready to go when the dialog is presented. You can use this same technique to do things like download customized documents that need to be prepared before they are streamed to the user's computer via fileDownload buttons in the dialog box as well.
As I said, this is a more complicated example, but it hits all the high points of your problem and mine. When the command button is clicked, the result is to first insure the backing bean is updated with the results of the pickList, then tell the backing bean to prepare streams for the user based on their selections in the pick list, then update the controls in the dynamic dialog with an update, then show the dialog box ready for the user to start streaming their content.
The trick to it was to use BalusC's order of events for the main commandButton and then to add the <p:ajax process="formPickList" /> bit to ensure it was executed first - because nothing happens correctly unless the pickList updated the backing bean first (something that was not happening for me before I added it). So, yea, that commandButton rocks because you can affect previous, pending and current components as well as the backing beans - but the timing to interrelate all of them is not easy to get a handle on sometimes.
Happy coding!
I am developing a JSF application and I have many user forms where I use JSF validations.
I have an issue which annoys me, it will be easier to tell it with an example.
<h:panelGroup>
<h:selectOneRadio id="gender" value="#{registrationController.person.gender}"
required="true" requiredMessage="#{msg.commonErrorBlankField}">
<f:selectItems value="#{registrationController.genders}" />
</h:selectOneRadio>
<rich:spacer />
<rich:message for="gender" errorLabelClass="errorLabel">
<f:facet name="errorMarker">
<h:graphicImage value="#{msg.imageExclamation}" />
</f:facet>
</rich:message>
</h:panelGroup>
Above if a radio option is not selected a required message is displayed. And when the user makes a selection I see the validation error disseapeares. Fair enough !
My problem is when the user navigates to next page and then by using back button of the browser comes back to this page again I can see my gender field is selected accordingly but validation error is still displayed.
Does anyone know if there is a workaround to clear the h:message field once I click the command button so validation error won't be displayed when I go back to the same page?
Not sure if this works. I have not tested it:
//idComponent is the Component whose message you want to clear, e.g. gender
void clearMessageForComponent (final String idComponent) {
if (idComponent != null) {
Iterator<FacesMessage> it = FacesContext.getCurrentInstance().getMessages(idComponent);
while(it.hasNext()){
((FacesMessage)it.next()).setDetail("");
}
}
}
It is important to understand that the browser back button won't trigger a request to the server.
that is not entirely correct, modern browsers do trigger a request if data was posted in previous stages of the navigation.
Clearing the Messages from the FacesContext won't fix your problem, since this will affect only the server side state of your application. Pushing the browser back button forces the clients browser to reload the page from the local browser cache.
It is important to understand that the browser back button won't trigger a request to the server.