2012-02-28 69 views
3

我爲後來的i18n定義了一些bean驗證消息。 此消息應驗證輸入的類型是數/ BigDecimal的:爲什麼我的bean驗證消息沒有被拾取?

class Payment { 
    @Digits(message = "test error msg", fraction = 2, integer = 13) 
    private BigDecimal amount; 
} 

<p:inputText value="#{payment.amount}" /> 

不幸的是,如果我嘗試輸入文本,我沒有得到我的定義味精,但:

'asd' must be a signed decimal number 

莫非有人解釋爲什麼?或者說,我如何強制我的輸入字段始終使用@Digits進行驗證?

回答

5

在JSF驗證後轉換髮生。如果您在映射到backing bean中的BigDecimal的文本字段中輸入的數字不是數字,JSF將嘗試將其轉換爲BigDecimal,當然它會失敗。所以Hibernate驗證器不會真的有機會參與其中。您需要本地化JSF轉換消息才能達到您想要的效果。

我不熟悉@Digits註解。但Hibernate Validator docs似乎表明它驗證數字是否使用了預期的整數和小數位數。因此,不要在文本字段中輸入文本,而是嘗試輸入與驗證程序無法接受的格式相同的值(在您的情況下,fraction = 2,integer = 13)。所以請嘗試輸入值123.123120,看看你是否得到預期的消息。

下面是進入實體並在轉換器中獲取註釋的黑客入侵。首先,你需要創建一些自定義的轉換器(在這種情況下,BigDecimal)的:

@FacesConverter("MyBigDecimalConverter") 
public class MyBigDecimalConverter extends NumberConverter { 
@Override 
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { 
    try { 
     HtmlInputText it = (HtmlInputText) arg1; 
     ValueExpression ve = it.getValueExpression("value"); 
     String expression = ve.getExpressionString(); 
     String field = expression.replaceAll("#\\{.*\\.", ""); 
     field = field.replace("}", ""); 
     String parent = expression.replace("." + field, ""); 
     ExpressionFactory expressionFactory = arg0.getApplication().getExpressionFactory(); 
     ValueExpression exp = expressionFactory.createValueExpression(arg0.getELContext(), parent, Object.class); 
     Object obj = exp.getValue(arg0.getELContext()); 

     Digits d = null;  
     Field f = obj.getClass().getDeclaredField(field); 
     d = f.getAnnotation(Digits.class); 
     return super.getAsObject(arg0, arg1, arg2); 
    } catch (ConverterException e) { 
     FacesMessage msg = new FacesMessage(d.message()); 
     msg.setSeverity(FacesMessage.SEVERITY_ERROR); 
     throw new ConverterException(msg); 
    } catch (Exception e) { 
     return super.getAsObject(arg0, arg1, arg2); 
    } 
} 

@Override 
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) { 
    return super.getAsString(arg0, arg1, arg2); 
} 

} 

而且你需要使用轉換器在你的頁面:

<h:outputText value="#{someBean.someEntity.nome}" /> 
    <h:form> 
     <p:inputText value="#{someBean.someEntity.someBigDecimal}" id="test"> 
      <f:converter converterId="MyBigDecimalConverter" /> 
     </p:inputText> 
     <h:message for="test"></h:message> 
     <p:commandButton value="teste" process="@form" update="@form"></p:commandButton> 
    </h:form> 

我在這裏使用primeFaces組件,但你並不需要它們。

轉換器到底在做什麼?它正在獲取bean中保存inputText引用的值和字段名稱的對象。然後,它找到該字段的@Digits註釋並讀取其消息。它要求NumericConverter將字符串轉換爲數字。如果失敗,它將使用@Digits註釋中的消息來顯示錯誤消息。

+0

是的,當我做了一個輸入,通過jsf我得到相應的hib驗證器味精。 – membersound 2012-02-28 16:02:09

+0

我想那回答你的問題呢?我很高興能夠提供幫助。乾杯 – Andre 2012-02-28 16:25:58

+0

不是。我仍然試圖強制驗證休眠,並跳過jsf驗證。如下所述,即使我完全刪除標籤,f:validateBean也不適用於我。 JSF似乎默認將映射驗證爲支持BigDecimal。而且我還沒有找到任何可以禁用這個特定功能的東西。 – membersound 2012-02-28 17:11:14

0

您應該使用<f:validateBean />來驗證委託給Bean驗證API(JSR 303)

<p:inputText value="#{payment.amount}" > 
    <f:validateBean /> 
</p:inputText> 
+0

這很奇怪。我試過這個標籤,但它不起作用。即使我完全刪除驗證標籤,仍然會發生JSF驗證。 – membersound 2012-02-28 16:02:35

0

不知道這<p:inputText>標籤,但在香草JSF你可以只:

<h:inputText id="price" 
    value="#{movieController.movie.price}" redisplay="true" 
    converterMessage="Please input a decimal"> 
    <f:ajax event="blur" render="numberOfCopiesMessage" /> 
</h:inputText> 

通知的converterMessage屬性。

雖然這可能看起來像違反DRY(因爲您已經在實體中有消息),但它沒有。您的模型與提交'asd'作爲整數的用戶無關 - 它確實是視圖內容

相關問題