JSF selectBooleanCheckbox在有条件呈现时不调用关联的setter方法

JSF selectBooleanCheckbox在有条件呈现时不调用关联的setter方法,jsf,Jsf,我正在JBoss 6.1.0 final上使用Mojarra 2.0.3。如果在标记中指定了条件呈现,则h:selectBooleanCheckbox的值设置器方法无法调用 具体而言: JSF: 问题是提交表单时从未调用setChecked()方法。如果删除“rendered”属性,将按预期调用setter。只有在有条件地呈现标记时,才会在提交时对其进行处理。在这两种情况下,通常都会调用getter 如果我设置了valueChangeListener,如果有条件地呈现selectBooleanC

我正在JBoss 6.1.0 final上使用Mojarra 2.0.3。如果在标记中指定了条件呈现,则h:selectBooleanCheckbox的值设置器方法无法调用

具体而言:

JSF:

问题是提交表单时从未调用setChecked()方法。如果删除“rendered”属性,将按预期调用setter。只有在有条件地呈现标记时,才会在提交时对其进行处理。在这两种情况下,通常都会调用getter

如果我设置了valueChangeListener,如果有条件地呈现selectBooleanCheckbox,也不会调用它。最后,将h:selectBooleanCheckbox标记封装在一个容器(如:panelGrid)中,并在“outside”组件上设置条件呈现会导致相同的行为。如果有条件地呈现复选框,则该复选框似乎不会被处理

这似乎是一件基本的事情,所以我假设我遗漏了一些东西。有没有人有过类似的经历

更新:本例中的托管bean是CDI会话范围的bean。进一步的调试似乎表明,在JSF生命周期的某个地方实例化并使用了另一个bean实例。因此,我修改了bean,在postConstruct方法中将对话设置为非瞬态。这导致JSF在计算“rendered”属性中使用的EL表达式时引发以下异常:

23:41:12179警告[javax.enterprise.resource.webcontainer.jsf.lifecycle]/admin/edit_user_profile.xhtml@41,72 rendered=“#{profileEditor.isCurrentUser}”:java.lang.IllegalStateException:javax.el.eleException:/admin/edit_user_profile.xhtml@41,72=“#{profileEditor.isCurrentUser}”:java.lang.IllegalStateException
在com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111)[:2.0.3-]
位于javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)[:2.0.3-]
在javax.faces.component.UIComponentBase.isRendered(UIComponentBase.java:417)[:2.0.3-]
.
.
.
原因:java.lang.IllegalStateException
在com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:635)[:2.0.3-]
在com.sun.faces.context.FacesContextImpl.getExternalContext(FacesContextImpl.java:135)[:2.0.3-]
在com.sgi.tds.web.admin.beans.TdsAdminBean.getCurrentUser(TdsAdminBean.java:36)[:]
在com.sgi.tds.web.admin.beans.UserProfileEditorBean.getIsCurrentUser(UserProfileEditorBean.java:153)[:]
在com.sgi.tds.web.admin.beans.UserProfileEditorBean$Proxy$\u$$\ uWeldClientProxy.getIsCurrentUser(UserProfileEditorBean$Proxy$\u$$\ uWeldClientProxy.java)[:]

作为攻击保护的一部分,当JSF对表单提交进行后处理时,将重新评估呈现的
属性。在您的特定情况下,它的计算结果为
false
,这只意味着您的bean是请求范围的,并且您没有在bean的(post)构造函数中保留属性值

如果不能保存它,那么需要将bean放在视图范围中

@ManagedBean
@ViewScoped
public class Somebean {

    // ...
}

这样,只要您与同一视图交互,bean实例就会一直存在。另请参见此相关问题/答案:

实际上,我在Primefaces中的深嵌套也有同样的问题,渲染精细且无法渲染(始终为false)。一般来说,巴卢斯是对的,但我注意到这种行为在深巢中。我想用一个完整的简单测试用例来复制它,我把责任归咎于Primefaces引擎中的渲染顺序,但这可能是更微妙的事情。谢谢你的回答。该bean实际上是一个CDI RequestScope bean,它应该与JSF ViewScope等效,但并不总是这样。FWIW,如果我包含“disabled”属性而不是“rendered”,我会观察到相同的行为,这似乎表明这里发生了其他事情。不,不应该是这样。使用JSF
@ViewScoped
或CDI
@ConversationScoped
或在bean的(post)构造函数中保存条件。禁用的
属性问题也不例外。它有相同的根本原因,在应用请求值阶段也会重新评估它。请参阅相关链接。对不起,我的错。当我指的是会话范围时,我编写了RequestScope。支持bean是一个CDI会话范围的bean。无论如何,我修改了bean,将会话设置为PostConstruct中的非瞬态,因为进一步的调试表明JSF在处理过程中获得了bean的另一个副本。现在,我已经让JSF在尝试获取用于评估所讨论的“呈现”的bean代码中的ExternalContext时抛出了一个IllegalStateException。我将尽快发布堆栈跟踪作为对此帖子的回应。对不起,我没有CDI的实际操作经验,也没有对其工作的深入了解,因此我无法说出可能的原因。然而,获取另一个bean副本的症状听起来很熟悉:每当您通过EL将其属性之一绑定到标记处理程序(在视图构建期间运行)时,
@ViewScoped
bean就会暴露相同的症状。另请参阅,我将使用尽可能小的视图/bean测试示例重试,而不使用任何其他标记/组件。非常感谢您的帮助。这个问题确实是由JSF在处理post期间实例化托管bean的另一个实例引起的。由于bean的这个新副本是“按原样”使用的,没有调用实例变量的setter,因此这种行为充其量是不正确的。我会看看你关于这个主题的其他帖子,看看我是否能想出一个解决办法。但我不能相信这被认为是JSF实现的一个“特性”。
private Boolean checked = new Boolean(false);

public Boolean getChecked() {return checked;}

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

public boolean getRender() {return true;}
@ManagedBean
@ViewScoped
public class Somebean {

    // ...
}