【问题标题】:Why does f:validateDoubleRange only work for @SessionScoped?为什么 f:validateDoubleRange 仅适用于 @SessionScoped?
【发布时间】:2011-11-18 17:07:15
【问题描述】:

有人可以向我解释为什么我的示例中的 Foo 在到达 validateDoubleRange 类时总是为 null 吗?最终结果是验证器的最小值始终为 0。当在 outputText 元素中时,数字 3 在页面上显示得很好。 如果我将 bean 设为 @SessionScoped 而不是 @ViewScoped,则验证良好

控制器:

import java.io.Serializable;
import java.math.BigDecimal;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ViewScoped
@ManagedBean(name = "fooController")
public class FooController implements Serializable {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FooController.class);
    private static final long serialVersionUID = 1L;
    private Foo foo;
    private BigDecimal amount;
    private Long fooId;

    public Long getFooId() {
        return fooId;
    }

    public void setFooId(Long fooId) {
        this.fooId = fooId;
        this.foo = new Foo();
        foo.setFooId(fooId);
        foo.setMinAmount(Double.valueOf(3));
        foo.setMaxAmount(Double.valueOf(10));
    }

    public Foo getFoo() {
        return foo;
    }

    public void sendAmount() {
        log.debug("sendAmount: " + amount);
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public static class Foo {

        private Long fooId;
        private Double minAmount;
        private Double maxAmount;

        public Foo() {
        }

        public void setFooId(Long fooId) {
            this.fooId = fooId;
        }

        public void setMinAmount(Double minAmount) {
            this.minAmount = minAmount;
        }

        public void setMaxAmount(Double maxAmount) {
            this.maxAmount = maxAmount;
        }

        public Long getFooId() {
            return fooId;
        }

        public Double getMaxAmount() {
            return maxAmount;
        }

        public Double getMinAmount() {
            return minAmount;
        }
    }
}

JSP:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html"
            >
<f:metadata>
    <f:viewParam name="fooId" value="#{fooController.fooId}" />        
</f:metadata>
<h:form id="myForm">
    <h:outputText value="This is correctly displayed: '#{fooController.foo.minAmount}'"/><br/>
    <h:outputText value="My Input:" />
    <h:inputText id="myInput"
                 value="#{fooController.amount}" 
                 required="true"
                 >
        <f:convertNumber maxFractionDigits="2"/>
        <f:validateDoubleRange minimum="#{fooController.foo.minAmount}" maximum="80"/>
    </h:inputText>
    <h:message for="myInput"/>
    <br/>
    <h:commandButton id="myButton"
                     value="Save Amount"
                     action="#{fooController.sendAmount}"
                     >
    </h:commandButton>
</h:form>
</ui:composition>

我在 JBoss 6.1 上使用 JSF 2

如果您在@BalusC 那里,这是我能想到的最简单的示例,并且与昨天的问题相同,我希望只是澄清且更易于复制。

-- 编辑,我应该添加 fooId 是通过视图参数设置的,所以你需要在 URL 的末尾加上 ?fooId=3。

【问题讨论】:

    标签: java validation jsf jakarta-ee jsf-2


    【解决方案1】:

    我现在明白为什么我昨天无法重现这个了。在我的游乐场环境中,我不小心设置了与默认值不同的以下上下文参数:

    <context-param>
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
        <param-value>false</param-value>
    </context-param>
    

    此问题与 JSF issue 1492 有关。 &lt;f:validateDoubleRange&gt; 其属性由 EL 绑定到视图范围的 bean 属性,由于令人讨厌的鸡蛋问题,将隐式重新创建整个 bean,因为验证器是基于每个请求创建的,并且这些属性将通过验证器传递建设。


    如果您不想禁用部分状态保存(非常合理),那么最好的办法是自己在视图范围的托管 bean 中创建并保存验证器:

    public Validator getValidator() {
        return new DoubleRangeValidator(foo.getMaximum(), foo.getMinimum());
    }
    

    (请注意,在 getter 中执行此操作是一个糟糕的设计,但由于您在 setter 中准备 foo 而不是 preRenderView 侦听器方法,因此没有其他方法,否则将是在同一个监听器方法中完成)

    <h:inputText validator="#{fooController.validator.validate}" ...>
    

    或者,或者,为替换 &lt;f:validateDoubleRange&gt; 的内容创建一个自定义验证器:

    <f:validator validatorId="bindableDoubleRangeValidator" />
    <f:attribute name="minimum" value="#{fooController.foo.minAmount}" />
    <f:attribute name="maximum" value="#{fooController.foo.maxAmount}" />
    

    package com.example;
    
    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.validator.DoubleRangeValidator;
    import javax.faces.validator.FacesValidator;
    import javax.faces.validator.ValidatorException;
    
    @FacesValidator("bindableDoubleRangeValidator")
    public class BindableDoubleRangeValidator extends DoubleRangeValidator {
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            setMinimum((Double) component.getAttributes().get("minimum"));
            setMaximum((Double) component.getAttributes().get("maximum"));
            super.validate(context, component, value);
        }
    
    }
    

    更新:自 Mojarra 2.1.18(2013 年 1 月)以来,鸡蛋问题 1492 已得到修复。因此,如果您最近偶然发现了这一点,那么您也可以考虑升级。

    【讨论】:

    • 哇,内容丰富且乐于助人。我想我可能要疯了。非常感谢。
    猜你喜欢
    • 2016-01-23
    • 2012-03-23
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 2018-03-03
    • 1970-01-01
    • 2022-08-19
    相关资源
    最近更新 更多