Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input value doesn't clear after validation failure

I've searched a lot and haven't found a solution.

I'm using JSF 2.1 and RichFaces 4.2.3 and want to validate the login data of the user

I have two input fields. One Username and one Password, both with @NotEmpty

login.xhtml

<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:mt="http://java.sun.com/jsf/composite/components">
<h:body>
<ui:composition template="/protected/user/login-template.xhtml">
    <ui:define name="panel-navigation">
        <ui:include src="/protected/user/login-left-menu.xhtml" />
    </ui:define>
    <ui:define name="contentbody">
        <h:form>
            <div id="content">
                <div class="subcolumns">
                    <div class="c65l">
                        <div class="subcl">
                            <p class="sum-error-message" />
                            <fieldset>
                                <h3>
                                    <h:outputText value="#{styleguideMessages.login}" />
                                </h3>
                                <p>
                                    <h:outputText value="#{messages.login_text}" />
                                </p>
                                <div class="subcolumns">
                                    <mt:inputText
                                        id="loginName"
                                        value="#{authenticationPM.loginName}"
                                        label="#{messages.general_label_loginname}"
                                        required="true" />
                                    <div class="c33r validation"></div>
                                </div>
                                <div class="subcolumns">
                                    <mt:inputText
                                        id="password"
                                        value="#{authenticationPM.password}"
                                        label="#{styleguideMessages.db_password}"
                                        required="true"
                                        secret="true" />
                                    <div class="c33r validation"></div>
                                </div>
                                <div class="subcolumns">
                                    <h:commandLink
                                        id="loginButton"
                                        action="#{authenticationPM.doLogin}"
                                        value="#{styleguideMessages.login}"
                                        title="#{styleguideMessages.login}"
                                        styleClass="button last" />
                                </div>
                            </fieldset>
                        </div>
                    </div>
                </div>
            </div>
            <mt:commandButton
                id="login"
                action="#{authenticationPM.doLogin}"
                value="hidden"
                style="visibility:hidden" />
        </h:form>
        <script
            src="#{facesContext.externalContext.requestContextPath}/js/lib/loginEnter.js"
            type="text/javascript"
            charset="utf-8"></script>
    </ui:define>
</ui:composition>

AuthentificationPM.java

import *;

@Named
@SessionScoped
public class AuthenticationPM extends AbstractPM implements Serializable {

/**
 * The user name from the login.
 */
private String userName;

/**
 * password.
 */
private String password;

/**
 * Returns the login name.
 * 
 * @return String
 */
@NotNull
@Pattern(regexp = "^[^\"/\\[\\]:;|=,+?*<>]*$", message = "{user.loginname.pattern}")
public String getLoginName() {
    return userName;
}

/**
 * Returns the password.
 * 
 * @return String
 */
@NotNull
public String getPassword() {
    return password;
}

/**
 * Sets the login name.
 * 
 * @param loginName
 *            - the login name of the user
 */
public void setLoginName(String loginName) {
    this.userName = loginName;
}

/**
 * Sets the password.
 * 
 * @param password
 *            - the password of the user
 */
public void setPassword(String password) {
    this.password = password;
}

}

If one of those (say the password) is not filled, the validation fails and a message is shown (as it should).

Now I delete the username and type in a password. The validation fails because the username is empty. It cleans the password field and displays a message for the username.

And now the error happens: the former entered username reappeares! How can I prevent this behaviour?

I know that after process validation, the update model values and invoke application are skipped and the render response is executed. As described here. The render response takes the values stored in the ui component (at apply requests) and uses them to rerender instead of deleting the invalid value.

I've tried this solution as well as this idea. Both ways don't find my component.

Any help or ideas are very appreciated.

Greetings, Kevin

like image 299
Wavemaster Avatar asked Oct 21 '22 00:10

Wavemaster


1 Answers

If you just erase the username from the inputfield, the value should be submitted as an empty string, which would be a legit replacement for the username and also matches the pattern defined.

I can only assume, that you have configured

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

in your web.xml. So, when you try to submitt an empty field, it is interpreted as null, which will not match your @NotNull Annotation on the username attribute. So, the setting of the value is canceled and it will maintain its prior state, cause it's SessionScoped - which is the username that has been entered once.

At least this is the only szenario a (String-)value is not updated when an empty string is submitted I can imagine.

Having this value set to true allows to reproduce the behavior you are describing.


You might ask, why this does not apply for your textbox where you are entering the password when erasing it? Since you are using secret="true" the text-box will not show any information about the string entered (i.e. the length), even if the backing bean attribute is not set to null (after removing the password) and still contains the wrong password.

But be aware that simply removing this attribute might screw functionality where other devs are relying on to get null instead of the empty string. So you should maybe consider to remove the @NotNull annotation and check for null manually.

like image 117
dognose Avatar answered Dec 21 '22 23:12

dognose