JSF 2 - Bean 验证:验证失败 ->空值替换为来自托管 bean 的最后一个有效值 [英] JSF 2 - Bean Validation: validation failed -> empty values are replaced with last valid values from managed bean

查看:16
本文介绍了JSF 2 - Bean 验证:验证失败 ->空值替换为来自托管 bean 的最后一个有效值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我不明白 JSF2 在验证期间的行为.希望可以有人帮帮我.


I do not understand the behaviour of JSF2 during valdation. Hope someone can help me.

我有一个表单,在(ajax)提交后验证字段 - 好的
如果验证失败,则会显示错误消息 - ok

I have a form where the fields are validated after (ajax) submit - ok
If the validation failed a error message is shown - ok

在我的示例中,当我输入一个有效的 生日 并且 name 字段为空时,提交后会显示 name 的错误消息.
现在,当我输入一个有效的 name 并从 birthday 字段中删除输入时,会显示 birthday 的错误消息(没关系)但现在是旧的'valid' birthday 也在输入字段中!?!

For my example when I enter a valid birthday and the field name is empty an errormessage for name is shown after submit.
Now when I enter a valid name and delete the input from the birthday field an errormessage is show for birthday (that's ok) but now the old 'valid' birthday stands also in the input field!?!

我怎样才能避免这种行为?当我提交一个空字段时,我想看到一条错误消息和一个空字段...

How can I avoid this behaviour? When I submit an empty field I want to see an errormessage and an empty field...

这是我的示例代码:

我使用包含 EntityBean (Contact) 的 ManagedBean (TestBean).Contact 包含每个注释的验证.

I use a ManagedBean (TestBean) that contains an EntityBean (Contact). The Contact contains validations per annoations.

public class Contact implements Serializable {
    @NotNull 
    @Temporal(TemporalType.DATE)
    private Date birthday;

    @NotNull 
    @Size(min=3, max=15)
    private String name;

    //...
}

我的ManagedBean:

@ManagedBean
@ViewScoped
public class TestBean implements Serializable {
    private Contact contact;

    @PostConstruct
    void init() {
        System.out.println("init...");
        contact = new Contact(); 
    }

    public void newContact(ActionEvent ae) {
        System.out.println("newContact...");
        contact = new Contact();
    }

    public void save() {
        System.out.println("save...");
        //TODO do something with contact...
    }

    public Contact getContact() { return contact; }

    public void setContact(Contact contact) {this.contact = contact;}
}

这里是我的 JSF 页面:

An here my JSF page:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" >      
 <h:body>
    <h:form>     
        <h:panelGrid columns="3">   

        <h:outputText value="Birthday: " />  
        <h:inputText id="birthday" value="#{testBean.contact.birthday}">
            <f:convertDateTime/>
        </h:inputText>  
        <h:message for="birthday" />  

        <h:outputText value="Name: " />  
        <h:inputText id="name" value="#{testBean.contact.name}"/>
        <h:message for="name" />

        </h:panelGrid>  

        <h:commandButton value="submit" action="#{testBean.save}"> 
            <f:ajax execute="@form" render="@form"/>
        </h:commandButton> 

        <h:commandButton value="newContact" actionListener="#{testBean.newContact}"
                         immediate="true"> 
            <f:ajax render="@form"/>
        </h:commandButton> 

    </h:form>
</h:body>
</html>

最后一个来自 web.xml 的片段

at last a snippet from web.xml

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
    <param-value>true</param-value>
</context-param>

感谢您的建议

推荐答案

您的特定问题是由

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

以及 Mojarra 的 HtmlBasicRenderer#getCurrentValue() 中的一个错误(至少是一个疏忽):

and a bug (at least, an oversight) in HtmlBasicRenderer#getCurrentValue() of Mojarra:

if (component instanceof UIInput) {
    Object submittedValue = ((UIInput) component).getSubmittedValue();
    if (submittedValue != null) {
        // value may not be a String...
        return submittedValue.toString();
    }
}

String currentValue = null;
Object currentObj = getValue(component);
if (currentObj != null) {
    currentValue = getFormattedValue(context, component, currentObj);
}
return currentValue;

通常情况下,当UIInput 组件成功转换和验证时,提交的值会设置为null.当 JSF 将要重新显示该值时,它首先检查提交的值是否不是 null,然后再继续重新显示模型值.但是,对于这个上下文参数,当它无效时它是 null 而不是空字符串,因此当您删除必填字段的初始值时,它将始终重新显示原始模型值.

Normally, the submitted value is set to null when the UIInput component is successfully converted and validated. When JSF is about to redisplay the value, it first checks if the submitted value is not null before proceeding to redisplay the model value. However, with this context parameter, it is null instead of an empty string when it is invalid and thus it will always redisplay the original model value when you remove the initial value of a required field.

要测试它,请将该上下文参数值设置为 false 或将其完全删除.您会看到它按预期工作.但是,它会带来一个缺点,即您的模型值将在空但非必需的字段上被空字符串弄乱,并且您将失去使用 JSR 303 bean 验证的 @NotNull 注释的优势.

To test it, set that context param value to false or remove it altogether. You'll see that it works as intended. However, it will bring back the disadvantage that your model values will be cluttered with empty strings on empty but non-required fields and you'll lose the advantage of using @NotNull annotation of JSR 303 bean validation.

要解决此问题,您必须按如下方式更改 HtmlBasicRenderer#getCurrentValue() 的第一部分:

To fix this, you've to alter the first part of HtmlBasicRenderer#getCurrentValue() as follows:

if (component instanceof UIInput && !((UIInput) component).isValid()) {
    Object submittedValue = ((UIInput) component).getSubmittedValue();
    if (submittedValue != null) {
        // value may not be a String...
        return submittedValue.toString();
    } else {
        return null;
    }
}

我已经将其作为 issue 2266 报告给 Mojarra 人员.

I've already reported it to Mojarra guys as issue 2266.

这篇关于JSF 2 - Bean 验证:验证失败 ->空值替换为来自托管 bean 的最后一个有效值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆