2011-09-16 36 views
11

Ai đó có thể giải thích cho tôi lý do tại sao Foo trong ví dụ của tôi luôn luôn là null khi nó được vào lớp validateDoubleRange? Kết quả cuối cùng là giá trị min cho trình xác nhận luôn là 0. Số 3 hiển thị tốt trên trang khi trong phần tử outputText. Nó xác nhận tốt nếu tôi làm cho đậu @SessionScoped thay vì @ViewScopedTại sao f: validateDoubleRange chỉ hoạt động cho @SessionScoped?

Bộ điều khiển:

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> 

Tôi đang sử dụng JSF 2 trên JBoss 6.1

Nếu bạn là ngoài đó là @BalusC, đây là ví dụ đơn giản nhất mà tôi có thể đưa ra, và cũng là vấn đề tương tự như hôm qua, chỉ, tôi hy vọng, làm rõ và đơn giản hơn để nhân rộng.

- chỉnh sửa, tôi nên thêm fooId đó được đặt thông qua tham số chế độ xem, vì vậy bạn cần? FooId = 3 ở cuối URL của bạn.

Trả lời

14

Tôi bây giờ thấy lý do tại sao tôi không thể tái tạo ngày hôm qua. Trong môi trường sân chơi của tôi, tôi đã vô tình các param bộ bối cảnh sau đây khác với giá trị mặc định:

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

Vấn đề này có liên quan đến JSF issue 1492. <f:validateDoubleRange> thuộc tính của EL được gắn với một thuộc tính bean scoped view sẽ tái tạo hoàn toàn toàn bộ bean do vấn đề gà-trứng khó chịu, bởi vì trình duyệt tính hợp lệ được tạo trên cơ sở theo yêu cầu và các thuộc tính đó được chuyển cho xây dựng của trình duyệt tính hợp lệ.


Nếu bạn không muốn vô hiệu hóa tiết kiệm nhà nước một phần (rất hợp lý), sau đó đặt cược tốt nhất của bạn là tạo ra và giữ validator trong giao diện scoped quản lý đậu tự hỏi:

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

(lưu ý, làm công cụ này trong thiết bị getter là thiết kế tồi, nhưng vì bạn đang chuẩn bị foo trong setter thay vì phương thức nghe preRenderView, không có cách nào khác, nếu không nó sẽ được thực hiện ngay trong cùng phương pháp nghe)

với

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

Hoặc cách khác, để tạo ra một validator tùy chỉnh cho rằng thay thế các <f:validateDoubleRange>:

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

với

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

} 

Cập nhật: vấn đề trứng gà 1492 được sửa từ Mojarra 2.1.18 (tháng 1 năm 2013). Vì vậy, nếu bạn vấp ngã khi những ngày này, sau đó bạn cũng có thể xem xét để chỉ cần nâng cấp.

+0

Wow, rất nhiều thông tin và hữu ích. Tôi nghĩ rằng tôi có thể đã phát điên. Cảm ơn rất nhiều. – Simon

+0

Bạn được chào đón. – BalusC

Các vấn đề liên quan