2011-09-16 48 views
11

有人可以向我解释为什么我的示例中的Foo在获取validateDoubleRange类时始终为空?最终的结果是验证器的最小值始终为0.编号3在outputText元素中时显示在页面上。 它验证罚款,如果我做,而不是豆@SessionScoped@ViewScoped为什么f:validateDoubleRange仅适用于@SessionScoped?

控制器:

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。

回答

14

我现在明白为什么我不能重现这个昨天。在我的游乐场环境我不得不小心以下方面的参数组不同于默认值:

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

这个问题与JSF issue 1492。一个<f:validateDoubleRange>的属性被绑定到一个视图范围的bean属性的EL会因为一个讨厌的鸡蛋问题而隐式地重新创建整个bean,因为验证器是基于每个请求创建的,并且这些属性将在验证器的构造上传递。


如果你不想禁用部分国家储蓄(非常合理的),那么你最好的选择是建立并保持在视图中验证作用域确定为自己的托管bean:

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

(请注意,在吸气剂中做这件事是一个糟糕的设计,但由于您正在准备foo而不是preRenderView听众的方法,所以没有其他方法,否则它将以相同的听众方法完成)

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

,或者,创建一个自定义的验证对于它取代了<f:validateDoubleRange>

<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被修复。所以如果你偶然发现这些日子,那么你也可以考虑升级。

+0

哇,非常丰富和有益的。我以为我可能会发疯。非常感谢。 – Simon

+0

不客气。 – BalusC

相关问题