Java 为什么f:validatedoubrerange只适用于@SessionScoped?

Java 为什么f:validatedoubrerange只适用于@SessionScoped?,java,validation,jsf,jakarta-ee,jsf-2,Java,Validation,Jsf,Jakarta Ee,Jsf 2,有人能解释一下为什么我的示例中的Foo在到达validatedoublrange类时总是为null吗?最终结果是验证程序的最小值始终为0。当在outputText元素中时,数字3在页面上显示得很好。 如果我使bean@SessionScoped而不是@ViewScoped 控制器: import java.io.Serializable; import java.math.BigDecimal; import javax.faces.bean.ManagedBean; import javax.

有人能解释一下为什么我的示例中的Foo在到达validatedoublrange类时总是为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>



我在JBoss6.1上使用JSF2

如果你在那里@BalusC,这是我能想到的最简单的例子,和昨天的问题一样,只是,我希望,澄清了,更容易复制


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

我现在明白了为什么我昨天无法复制它。在我的游乐场环境中,我意外地将以下上下文参数设置为与默认值不同:


javax.faces.PARTIAL_STATE_保存
假的
这个问题与JSF有关。一个
的属性通过EL绑定到一个视图范围的bean属性,由于一个棘手的鸡蛋问题,它将隐式地重新创建整个bean,因为验证器是基于每个请求创建的,并且这些属性将在验证器的构造中传递


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

public Validator getValidator() {
    return new DoubleRangeValidator(foo.getMaximum(), foo.getMinimum());
}
(注意,在getter中执行此操作是一种糟糕的设计,但是由于您在setter中准备
foo
,而不是
preRenderView
侦听器方法,因此没有其他方法,否则将在相同的侦听器方法中正确执行)



或者,为替换
的验证程序创建自定义验证程序:




更新:自Mojarra 2.1.18(2013年1月)以来,1492年的鸡蛋问题已得到解决。所以,如果你现在遇到了这个问题,那么你也可以考虑升级。

哇,非常有帮助和有帮助。我想我可能是疯了。非常感谢。
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);
    }

}