2
votes

I'm using Mojarra 2.0.3 on JBoss 6.1.0 final. I'm having a problem with the value setter method for an h:selectBooleanCheckbox not being called if conditional rendering is specified in the tag.

Specifically:

JSF:

<h:selectBooleanCheckbox value="#{somebean.checked}" rendered="#{somebean.render}" />

Example bean code:

private Boolean checked = new Boolean(false);

public Boolean getChecked() {return checked;}

public void setChecked(Boolean checked) {this.checked = checked;}

public boolean getRender() {return true;}

The problem is that the setChecked() method is never called when the form is submitted. If I remove the "rendered" attribute, the setter will be called as expected. It's only when the tag is conditionally rendered that it is not processed on submit. The getter is called normally in either case.

If I set a valueChangeListener, this is also not invoked if the selectBooleanCheckbox is conditionally rendered. Finally, enclosing the h:selectBooleanCheckbox tag in a container like an :panelGrid and setting the conditional rendering on the "outside" component results in the same behavior. It seems that the checkbox won't be processed if it is conditionally rendered.

This seems like kind of a basic thing, so I'm assuming there is something I'm missing. Does anyone have any similar experience with this?

UPDATE: The managed bean in this case is a CDI ConversationScoped bean. Further debugging seemed to suggest that another instance of the bean instantiated and used somewhere in the JSF lifecycle. So I modified the bean to set the conversation to non-transient in the postConstruct method. This caused JSF to throw the following exception while evaluating the EL expression used in the "rendered" attribute:

23:41:12,179 WARNING[javax.enterprise.resource.webcontainer.jsf.lifecycle] /admin/edit_user_profile.xhtml @41,72 rendered="#{profileEditor.isCurrentUser}": java.lang.IllegalStateException: javax.el.ELException: /admin/edit_user_profile.xhtml @41,72 rendered="#{profileEditor.isCurrentUser}": java.lang.IllegalStateException
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) [:2.0.3-]
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190) [:2.0.3-]
    at javax.faces.component.UIComponentBase.isRendered(UIComponentBase.java:417) [:2.0.3-]
.
.
.
Caused by: java.lang.IllegalStateException
    at com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:635) [:2.0.3-]
    at com.sun.faces.context.FacesContextImpl.getExternalContext(FacesContextImpl.java:135) [:2.0.3-]
    at com.sgi.tds.web.admin.beans.TdsAdminBean.getCurrentUser(TdsAdminBean.java:36) [:]
    at com.sgi.tds.web.admin.beans.UserProfileEditorBean.getIsCurrentUser(UserProfileEditorBean.java:153) [:]
    at com.sgi.tds.web.admin.beans.UserProfileEditorBean$Proxy$_$$_WeldClientProxy.getIsCurrentUser(UserProfileEditorBean$Proxy$_$$_WeldClientProxy.java) [:]
1
Actually I'm having the same problem with deep nests in Primefaces, <h:inputText> renders fine and <h:selectBooleanCheckbox> fails to render (always false). Generally speaking Balus is right--but I have noticed this behavior in deep nests. I'd be interested in a complete simple test case to replicate it, I was blaming rendering order in the Primefaces engine, but it might be something more subtle.Daniel B. Chapman

1 Answers

2
votes

As part of attack safeguard, the rendered attribute is re-evaluated when JSF postprocesses the form submit. That it evaluates false in your particular case can only mean that your bean is request scoped and that you didn't preserve the attribute value in bean's (post)constructor.

If you can't preserve it, then you need to put the bean in the view scope.

@ManagedBean
@ViewScoped
public class Somebean {

    // ...
}

This way the bean instance lives as long as you're interacting with the same view. See also this related question/answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated