Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the condition #{facesContext.postback and not facesContext.renderResponse} mean?

Tags:

el

jsf-2

I was checking out the code for this template from the OmniFaces Showcase app, when I encountered the following condition used in a p:selectOneMenu:

disabled="#{facesContext.postback and not facesContext.renderResponse}"

From using the app, it seemed that the selectOneMenu is never disabled, so what does this code really do?

I know that facesContext.postback is true whenever the page is resultant from POST requests generated by JSF components (commandButton/commandLink, etc), but what would be the usual expected state of facesContext.renderResponse when evaluated in the View?

UPDATE: oops, just now I saw the comment: They're disabled in other phases than render response, because they otherwise complain that the model value cannot be set even though there's no form.

So, I'm guessing the condition is evaluated several times during Faces lifecycle, and the component is disabled until the last state (renderResponse) is reached, when facesContext.renderResponse evaluates to true, the whole expression evaluates to false and the component is then enabled. Is that about right?

like image 472
Elias Dorneles Avatar asked Dec 28 '12 11:12

Elias Dorneles


1 Answers

Those <p:selectOneMenu> components are actually abused to have a nice <div><ul><li> dropdown menu with a minimum of code ;) Their values represent the current menu group and page which are by design read-only (they have no setter method). The navigation takes place by JavaScript window.location which is handled during change event. They are not part of any form and do not participate in any form submit.

The disabled attribute is theoretically not mandatory, but when a non-ajax JSF form elsewhere in the very same page is submitted synchronously, then PrimeFaces SelectOneMenuRenderer will still try to decode() it in its entirety even though it is not enclosed in any form at all. It would ultimately cause the following exception when the model value is to be updated because there's no setter for that value:

javax.el.PropertyNotWritableException: /WEB-INF/templates/showcase.xhtml @28,80 value="#{parent.children[0].viewId}": The class 'org.omnifaces.showcase.Page' does not have a writable property 'viewId'.
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
    at javax.faces.component.UIInput.updateModel(UIInput.java:818)
    at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
    at org.primefaces.component.panel.Panel.processUpdates(Panel.java:304)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
    at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
    at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)

When the disabled attribute evaluates true during postback, then the SelectOneMenuRenderer will skip the decode() during apply request values phase and thus also skip the update of model value. However, if it evaluates true as well during render response phase, then it becomes unselectable (and thus unusable). So, it should not evaluate true during render response phase. The expression

disabled="#{facesContext.postback and not facesContext.renderResponse}"

achieves exactly that. All with all, it's basically kind of a workaround for the odd behavior of SelectOneMenuRenderer (for which I've not really investigated the underlying cause yet).

To test it yourself, pull the project, remove the disabled attribute and invoke a synchronous submit in for example the <o:onloadScript> showcase page.

like image 165
BalusC Avatar answered Sep 21 '22 04:09

BalusC