为什么f:validateDoubleRange仅适用于@SessionScoped?

有人可以向我解释为什么我的例子中的Foo在到达validateDoubleRange类时总是为空? 最终结果是validation器的最小值始终为0.在outputText元素中,数字3在页面上显示正常。 如果我使用@SessionScoped而不是@ViewScoped来validation它是@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:

      

我在JBoss 6.1上使用JSF 2

如果你在那里@BalusC,这是我能提出的最简单的例子,和昨天一样,我希望,澄清并且更容易复制。

– 编辑,我应该补充说fooId是通过视图参数设置的,所以你需要在URL的末尾使用?fooId = 3。

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

  javax.faces.PARTIAL_STATE_SAVING false  

此问题与JSF 问题1492有关 。 一个其属性由EL绑定到视图范围的bean属性,将由于讨厌的鸡蛋问题而隐式重新创建整个bean,因为validation器是基于每个请求创建的,并且这些属性将被传递关于validation者的建设。


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

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

(注意,在getter中执行这些操作是一个糟糕的设计,但是因为你在setter而不是preRenderView监听器方法中准备foo ,所以没有其他办法,否则它将在同一个侦听器方法中完成)

  

或者,替代地,为替换那个创建自定义validation器:

    

 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); } } 

更新 :鸡蛋问题1492自Mojarra 2.1.18(2013年1月)起修复。 所以,如果你这些天偶然发现,那么你也可以考虑升级。