【问题标题】:h:selectOneRadio mapped to a Boolean value is converting nulls to falseh:selectOneRadio 映射到布尔值正在将空值转换为 false
【发布时间】:2016-07-12 04:05:16
【问题描述】:

我有一个 h:selectOneRadio 组件,我已映射到支持 bean 中的 Boolean(不是布尔值)。加载时,单选按钮没有默认选择选项,单选按钮不是必填字段。

示例代码:

JSF 页面摘录:

<h:form>
<h:selectOneRadio value="#{pagecode.test}">
    <f:selectItem itemValue="#{true}" itemLabel="Yes"/>
    <f:selectItem itemValue="#{false}" itemLabel="No"/>
</h:selectOneRadio>
<h:commandButton value="Save" action="#{pagecode.save}"/>
</h:form> 

支持 Java 页面代码:

package pagecode;

public class JSFBooleanTestView extends PageCodeBase {

    protected Boolean test;

    public Boolean getTest() {
        return test;
    }

    public void setTest(Boolean test) {
        this.test = test;
    } 

    public String save() {
        return "JSFBooleanTestView";
    }
}

faces-config.xml 摘录:

<managed-bean>
    <managed-bean-name>pagecode</managed-bean-name>
    <managed-bean-class>pagecode.JSFBooleanTestView</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

由于test 没有被默认为一个值,所以单选按钮开始时未选中。由于该字段不是必需的,我的期望是在未选择单选按钮的情况下按下保存按钮会导致测试为空。而是将 test 分配为 false。

我尝试过的不同选项都没有效果:

  1. 设置h:selectOneRadio required="false"

  2. 添加到 web.xml:

    <context-param>
         <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
         <param-value>true</param-value>
     </context-param>
    
  3. 添加到 web.xml:

     <context-param>
         <param-name>org.apache.el.parser.COERCE_TO_ZERO</param-name>
         <param-value>false</param-value>
     </context-param>
    

起作用的是将immediate="true" 添加到h:commandButton

我的问题:

  1. 是什么让h:selectOneRadio 正常地将空值转换为假?这是预期的行为吗?

  2. 为什么immediate="true" 使h:commandButton 不将空值转换为假? immediate="true" 在这种导致差异的特定情况下究竟做了什么不同的事情?我知道immediate="true" 将跳过 JSF 生命周期中的某些阶段,但我不明白在这些阶段中是什么导致了从 null 到 false 的转换。

编辑:

我刚刚意识到我在h:commandButton 中添加了immediate="true"不是h:selectOneRadio。我的问题已相应编辑。

这在使用 Apache MyFaces 2.0 的 IBM WebSphere Portal 8.0 上的 portlet 应用程序中使用。

【问题讨论】:

  • COERCE_TO_ZERO 不是上下文参数。这是一个 VM 参数(并且依赖于服务器)。将其设置为VM参数,重试,然后我们可以进一步讨论。在任何情况下,始终包含有关 JSF impl/version 和 server impl/version 的详细信息,否则任何阅读此问题的人都会假设他们最喜欢的 JSF 和服务器 impl 的最新版本。
  • @BalusC 哦!谢谢你。我编辑了我的问题以包含该附加信息。另外,我添加了 COERCE_TO_ZERO 作为 VM 参数,这确实使它按预期工作。 Your article 主要向我解释了原因,但您能否具体说明这与布尔值有何关系,以便我确定我理解正确?
  • @BalusC 另外,我们的服务器上有很多 portlet,我担心像这样进行服务器范围的 VM 更改。如果我改为使用 ServletContextListener 设置属性,它会只影响需要该属性的 portlet,还是会影响所有 portlet? System.setProperty 对我来说似乎很全球化,至少在我的理解中。
  • 默认情况下,Apache EL 错误地将原语包装器视为原语。 IE。 Boolean 被解释为booleanInteger 被解释为intCharacter 被解释为char,等等,它们的默认值将成为包装原语的默认值(false,@ 987654349@、\u0000 等)而不是 null。而且,对不起,它的应用范围很广。因此,如果代码错误地依赖空字符串作为正确的行为,事情可能会失败(尽管这通常只会暴露隐藏的错误,最终有机会真正修复,所以你实际上会很高兴;)。
  • 太好了,非常感谢! :) 你能把你的 cmets 放在一个答案中,这样我就可以接受它并给你信用吗?

标签: jsf jsf-2 null boolean selectoneradio


【解决方案1】:

原始包装器的行为,例如 BooleanIntegerDoubleCharacter 等获取原始默认值 false00.0\u0000null 是特定于 Apache EL 的,在 ao 中使用Tomcat、JBoss AS 和 WebSphere 服务器。它仅影响基于 EL 2.1 和 EL 2.2 的版本。从 EL 3.0 开始,这种不当行为已得到纠正(在我自己的 issue report 之后)。

使用org.apache.el.parser.COERCE_TO_ZERO 确实是解决方案,但您应该将其设置为VM 参数(系统属性),而不是上下文参数。对于这个特定问题,javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL 是不相关的,但您绝对应该保留它,以避免使用空字符串而不是 null 设置 String 类型值。

博客文章The empty String madness详细介绍了所有这些以及一些历史记录。

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    相关资源
    最近更新 更多