Primefaces poll triggers message from f:viewParam - validation

First post here, so bare a bit with me. Searched a lot, but either because I was to blind or because I just didn't use the correct search strings, I haven't found any answer relevant to my problem.
Basically, I have a web application written in Java and using Primefaces. I'm using a p:layout, having the main content in the center unit, the header in the north and the footer in the south unit of the layout. The west layout unit holds a p:poll which runs every two seconds cand calls a js function when the oncomplete event is triggered.
So far so good. The thing is that on a certain page, in the center layout unit, I have a f:viewParam which accepts only longs and, even though the value is valid, when the above poll gets executed, the requiredMessage from the f:viewParam appears.
After doing some intensive search, I've found that by adding a ignoreAutoUpdate="true" to the p:poll, the messages from the f:viewParam will not get triggered and the warning telling that I have to provide a valid id isn't shown.
So, my question is: by having the ignoreAutoUpdate="true" in my p:poll will compromise, by any chance, the f:viewParam validation? Or is it safe to leave it there?
Here is the relevan parts from my layout:
The poll form the west layout unit:
<h:form id="liveQueueForm">
<p:remoteCommand name="rcStart" action="#{liveQueueMB.startPoll()}"/>
<p:remoteCommand name="rcStop" action="#{liveQueueMB.stopPoll()}"/>
<p:poll id="liveQueueUpdater" delay="10" widgetVar="livePoll" interval="2" listener="#{liveQueueMB.init}" oncomplete="updateLiveQueue(xhr, status, args);" autoStart="true" partialSubmit="true" ignoreAutoUpdate="true" immediate="true" />
<div id="live-queue">
<div id="queue-holder"></div>
</div>
</h:form>
The f:metadata block which holds my f:viewParam:
<f:metadata>
<f:viewParam name="callId" value="#{viewInboundCallDetailsMB.callId}" required="true" requiredMessage="Please provide a valid call ID" converter="javax.faces.Long" converterMessage="The call ID is not numeric" />
<f:viewAction action="#{viewInboundCallDetailsMB.init}"/>
</f:metadata>
Thank you!

From Primefaces manual about ignoreAutoUpdate:
"If true, components which autoUpdate="true" will not be
updated for this request. If not specified, or the value is
false, no such indication is made."
Which means that it's not going to do update your viewParam component, and other components that have autoUpdate="true".
It's not going to disable the validation on it. (Unless of course, if you are using your poll for validation, which i presume you are not)

Related

Why does <o:validateAll> behave different than other validators?

I use OmniFaces' <o:validateAll> validator to validate a number of input components. This works fine as long as I do not put it into a RichFaces <rich:tabPanel>. When I do this and leave fields blank, validation fails (as expected), but the active tab is changed, regardless of the failed validation. Other validators I tried prevent the tabPanel from switching to another tab, whenever validation fails.
What could be the reason for this?
I'm currently using OmniFaces 2.1 and RichFaces 4.5.17.Final with Mojarra 2.2.12 on Wildfly 9.0.2.
Here is the XHTML code to reproduce the problem:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:o="http://omnifaces.org/ui"
xmlns:rich="http://richfaces.org/rich">
<h:form id="form">
<rich:messages />
<rich:tabPanel id="tabPanel">
<rich:tab id="tab1" header="Tab 1">
<h:inputText id="myDouble" value="#{someDoubleVal}">
<f:validateDoubleRange minimum="1.0" maximum="2.0"/>
</h:inputText>
<o:validateAll id="allValid" components="myDouble" message="Missing value!" />
</rich:tab>
<rich:tab id="tab2" header="Tab 2">
Just another tab to switch.
</rich:tab>
</rich:tabPanel>
</h:form>
</ui:composition>
Enter a value outside 1.0 and 2.0 and try switching to Tab 2 to see expected behavior, triggered by <f:validateDoubleRange>: a faces-message is displayed and the first tab is still active.
Leave input blank and try switching to Tab 2 to see behavior of <o:validateAll>: validation seems to fail (a faces-message is displayed), but Tab 2 is activated.
Update: The described behavior applies with switchType="ajax" (the default) as well as with switchType="server". In both cases, the tab-panel performs a submit of the included inputs, so from a users point of view, a tab-switch seems to be the same as a <h:commandButton> submit (technically there might be differences, I don't know the implementation details of the tab-panel).
If I perform the tab-switch via a regular <h:commandButton> with a <f:setPropertyActionListener>, the <o:validateAll> behaves the same way as the other validators, i.e. the tab-switch is not performed due to the validation error.
<rich:tabPanel id="tabPanel" activeItem="#{bb.activeTab}">
...
<rich:tab id="tab1" name="tab1" header="Tab 1">
...
<h:commandButton value="submit">
<f:setPropertyActionListener value="tab2" target="#{bb.activeTab}" />
</h:commandButton>
...
</rich:tab>
</rich:tabPanel>
Note: This is just a minimalistic example showing the problematic behavior. In my real code I have not just a single component validated by <o:validateAll> and I do actually associate the input values with a backing-bean. The observed behavior is exactly the same.
The problem is two-fold.
First problem is, <o:validateAll> doesn't explicitly call context.renderResponse() when validation has failed and leaves this job to JSF which will implicitly call it during validations phase when at least one input component is found invalid after <o:validateAll> has run, or otherwise during the subsequent update model values phase.
Second problem is, <rich:tabPanel> tab switch event is queued for update model values phase instead of for invoke application phase. I'm not sure why RichFaces guys designed it like that, but the consequence is that the tab switch event is fired anyway even when validation is found failed during the update model values phase only.
When you move <o:validateAll> before at least one associated input component, then JSF will implicitly call context.renderResponse() during validations phase already and therefore completely skip the update model values phase and therefore the queued <rich:tabPanel> tab switch event won't have chance to be invoked.
I have fixed it in OmniFaces 2.6-SNAPSHOT as per issue 322. When using OmniFaces 2.6 or newer, it should not anymore matter where <o:validateAll> is placed in the tree in order to achieve the desired behavior of <rich:tabPanel> tab switch event to not be invoked.

What is the client-side behavior of a JSF WebSocket when it is removed from the DOM

I have several panels, each displaying some contents, and zero, one, or more of these panels can be displayed, as in the following example:
<div jsf:id="contents">
<ui:fragment rendered="#{aContent.rendered}">
<h:form>
<o:socket channel="a-channel" onmessage"onAMessage"/>
<o:commandScript name="onAMessage"
actionListener=#{aContent.update()}"
render=":aComponent"/>
</h:form>
<my:aComponent id="aComponent" />
</ui:fragment>
<ui:fragment rendered="#{bContent.rendered}">
<h:form>
<o:socket channel="b-channel" onmessage"onBMessage"/>
<o:commandScript name="onBMessage"
actionListener=#{bContent.update()}"
render=":bComponent"/>
</h:form>
<my:bComponent id="bComponent" />
</ui:fragment>
</div>
I would like to know what happens to the client side web socket when one of these UI fragments is removed from the DOM after an AJAX update of the enclosing element.
Is the web socket closed?
Should I consider another approach?
Based on how it's currently implemented, it'll keep running. You need to repeat the condition in the connected attribute.
<ui:fragment rendered="#{aContent.rendered}">
<o:socket ... connected="#{aContent.rendered}" />
Perhaps this will be improved later when I plan to add <f:ajax> support for <o:socket>.
On the other hand, your code snippet is non-DRY. Try restricting to only 1 socket+commandScript combination which does its job dynamically based on contents of the pushed message. See also Channel design hints section of the documentation.

Disable validation for immediate actions

I have a complex page with a p:commanButton with actionListener and immediate="true"
Upon clicking this commandButton, I need to process a single inputField(thus skipping rest of the form). The problem is, that the inputField has a validator which I'd like to use only in full page submit.
<p:inputText id="#{cc.attr.id2}_input" value="#{myBB.value}"
immediate="true">
<f:validateLength minimum="4"/>
</p:inputText>
<p:commandButton id="#{cc.attr.id2}_search" immediate="true"
process="#{cc.attr.id2}_input #this"
actionListener="#{myBB.listener}">
</p:commandButton>
When I do this with i.e. 3 letters in the inputText, the myBB.value is not updated because of the failed validation. So I'd like to disable the validator for the inputField for the immediate processing by the commandButton. But I don't know how.
I know I can get the value from the ExternalContext, but this seems like a very hacky solution to me(and in my case is not even applicable, because it's inside composite component and I have no way of knowing the clientId of the textField.)
I also know about disabled attribute of the validator tag, but I have no idea how could I put that to use in this situation.
EDIT: I've changed a code a bit, because the IDs I'm using are actually not as simple as I first stated and don't allow me to use simple proposed solution.
I use Mojarra 2.2.4 and Primefaces 4.0
So, first of all, you haven't got the problem with immediate, but rather with <f:validateLength> validator.
That is, to rephrase your question, you'd like to skip validation of a given component in case the particular button is clicked.
Depending on whether you are on Mojarra 2.1.18+ or not there are two solutions. The first one is quite straightforward: use the disabled attribute of <f:validateLength>, while the other one takes into account issue 1492. As we've nowadays have advanced past the aforementioned version of Mojarra, I'll post the first and easier solution, otherwise, scroll through the excellent answers to Why does f:validateDoubleRange only work for #SessionScoped? and Disabled attribute of <f:validateLength> does not evaluate request parameters by BalusC.
So, the solution is the following:
<h:form id="formId">
<p:inputText id="inputId" value="#{myBB.value}">
<f:validateLength minimum="4" disabled=#{not empty param['formId:buttonId']}" />
</p:inputText>
<p:commandButton id="button" process="#this inputId" actionListener="#{myBB.listener}" />
</h:form>
As a side note, you can see that I didn't use immediate attribute at all because I supposed that you abused it to perform a given task. With the rise of AJAX in particular within JSF-based applications you can now easily group a subset of input elements validation by specifying the process attribute of <p:commandButton> or <p:ajax> instead of the previously used prioritized validation especially in synchronous requests. Only those components whose ids are supplied will be processed on the server and all other components will be omitted prom processing lifecycle. Also note that process="#this ..." is also mandatory to execute actions associated with the button itseld.
Regarding the appropriate usage of immediate I'd strongly suggest to refer to the classics: Debug JSF lifecycle blog post by BalusC to check whether you've used it correctly.

JSF2: Why is a surrounding <h:form> necessary for ajax listeners

Yesterday I was trying to implement a Listener for a SelectManyListbox using Ajax in JSF 2.
Following code is from my memory, since I dont have it available right now :-)
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:selectManyListbox value="#{myBean.myList}">
<f:ajax render="delete" listener="#{myBean.listener}" />
<h:selectManyListbox>
<h:commandbutton id="delete" disabled="#{myBean.disabled}" value="Delete" />
<h:body>
I tried a lot of different things because my listener was never called. In the end I just added a surrounding <h:form> tag and everything worked. Why is that?
My goal is a composite-control that just displays a list and enables/disables the delete-button when a item is selected/unselected. In my understanding a form is only needed when I want to submit multiple values at once.
Thanks
In my understanding a form is only needed when I want to submit multiple values at once.
This is thus untrue. A <h:form> is necessary when you want to send a POST request to the server by JSF by an UIInput component such as <h:selectManyListbox>. This is regardless of whether the POST request is performed by a regular (synchronous) request or an ajaxical (asynchronous) request. This is regardless of the amount of inputs. You should not forget that the javax.faces.ViewState hidden input field and if necessary also the name=value of the command button itself also needs to be sent along as well, so there's basically never means of a single input value in a JSF postback request.
POST has the major advantage over GET that there's no limit in the amount of data which can be sent. In GET this is dependent on the webbrowser used and ranges from 255 characters until 2~4KB in older browsers and 8~10KB in newer browsers. In POST the limit is usually around 2GB.

What is <f:ajax execute="#all"> really supposed to do? It POSTs only the enclosing form

sorry if I am being thick but what is the execute="#all" in an f:ajax tag really supposed to do? I expected it to submit all the elements on a page but it seems to POST only the values in the enclosing form, not all forms on page.
For example
<h:body>
<h:form id="form1">
Input1/Form1 <h:inputText id="testinput" value="#{testBean.input1}" />
</h:form>
<h:form id="form2">
Input2/form2 <h:inputText id="testinput2" value="#{testBean.input2}" />
<h:commandButton value="Ok" actionListener="#{testBean.al}">
<f:ajax execute="#all" />
</h:commandButton>
</h:form>
</h:body>
Only form2 is posted on click.
Using mojarra 2.0.2..
The execute="#all" was just a major oversight during designing JSF2 spec. JSF kind of abstracted away too much of its HTML form based nature, forgetting that it's ultimately actually a HTML code generator.
In HTML, submitting a different form than the enclosing one is disallowed. So execute="#all" will never work from that perspective on. It will behave exactly the same as execute="#form". Given that JSF is just a HTML code generator, the same "problem" will hit JSF too. It's not possible to process multiple <h:form> components at once.
If you really need to have this feature for some reason, you should take a step back and reconsider the incorrect way how you look at HTML forms. You need to make sure your forms are designed in such way that you never need information from another form.
See also:
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?.
PrimeFaces already realized early that #all was fundamentally wrong. That's exactly why they never supported #all in process attribute, their equivalent of execute. They initially also never supported #all in update, their equivalent of render. However, the only real world use case where that made sense was handling a full error page during an ajax exception, so they ultimately brought update="#all" back after I created the FullAjaxExceptionHandler. The process="#all" will still have exactly the same effect as process="#form".
However, the very same PrimeFaces library also unintentionally made the imagined behavior of execute="#all" possible via its later introduced partialSubmit="true" feature whereby you explicitly specify all other forms like below (the PFS #(form) is just for simplification, a hardcoded collection like :formId1 :formId2 :formId3 etc is also just possible).
<p:commandButton ... process="#(form)" partialSubmit="true" />
This works because partialSubmit="true" prepares the process="xxx" at client side rather than server side. In other words, instead of sending the entire enclosing form from server to client and then processing the specified inputs, it sends only the specified inputs from server to client and then processes them all. Do note that when partialSubmit is absent or set to false, then it would still only send the enclosing form. This misbehavior should rather not be relied upon. They may fix this misbehavior on their side sooner or later.
See also:
Any significant technical difference between JSF non-AJAX submit and a "#all" AJAX submit?
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
Here is a quote from JavaServer Faces 2.0 - The complete reference, page 352:
The execute and render keywords accept a set of special keywords, each with the meaning shown in this table:
#all (using with execute): Every component on the page is submitted and processed. This is useful when you want to do a full-page submit.
I think this quite clearly states that the fields from all forms should be submitted with the AJAX request.
However, even with Mojarra 2.0.3 this doesn't happen. Despite of contents of the execute attribute (whether you put a list of forms or #all) only the enclosing form gets its' fields submitted. So this seems like a bug. I am raising an issue about this unless there are altering views?
It would have to be execute=":form1 form2" (if you have the default separator), but anyway no, it doesn't. It only sends the second one.
If you put #all in the first form, it only sends the first. At least on Safari 5/Firefox 3.6.3 anyway. I guess one would have to look at the mojarra javascript to find out more.
Have you tried this?
<f:ajax execute="form1 form2" />
Does it send both forms' data if you explicitly mention them?
AFAIK, you are right: #all represents the whole page.

Resources