Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
136 views
in Technique[技术] by (71.8m points)

java - JSF 2 - Bean Validation: validation failed -> empty values are replaced with last valid values from managed bean


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

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

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...

Here's my sample code:

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;

    //...
}

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

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>

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>

Thanks for some tips

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your particular problem is caused by

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

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;

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.

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.

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...