eclipse-ee4j / mojarra

Mojarra, a Jakarta Faces implementation
Other
160 stars 109 forks source link

"Interpret empty string submitted value as null" must also be considered in HtmlBasicRenderer#getCurrentValue() #2266

Closed ren-zhijun-oracle closed 11 years ago

ren-zhijun-oracle commented 12 years ago

Consider this testcase:

<h:form>
    <h:inputText value="#{bean.input}" required="true" />
    <h:commandButton value="submit" />
    <h:messages />
</h:form>

with

private String input = "input";
// Getter+Setter

When you remove the value, the "value is required" validation error appears, which is perfectly fine. Also note that the input field is kept blank, as the enduser originally entered, which makes totally sense.

However, when you add this context parameter (which is often done to avoid the non-required model values being cluttered with empty strings and/or in order to be able to use JSR303 tt>@NotNull</tt annotation)

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

then the initial model value is redisplayed on validation error instead of the submitted value.

The culprit is in HtmlBasicRenderer#getCurrentValue().

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

One possible solution would be to check as well if it is invalid:

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

This is actually also more in line with the normal behaviour of UIInput#validate() method.

Environment

Mojarra 2.1.4

Affected Versions

[2.1.3]

ren-zhijun-oracle commented 6 years ago
ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented Reported by @BalusC

ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented bfrevel said: I have the same behavior in all components. For example the selectOneMenu component.

This is my testcase:

**TestBean.java**public class TestBean {
    @NotNull
    private String stringValue1;
    @NotNull
    private String stringValue2;
    @NotNull
    private Integer integerValue;

    //getter and setter methods 
    private void init() {
    stringValue1 = "test";
    stringValue2 = "String1";
    integerValue = 1;
    }

    public TestBean() {
    this.init();
    }
}
**page1.xhtml**...
<h:outputLabel value="StringValue1:" for="stringValue1" />
<h:inputText id="stringValue1" value="#{testBean.stringValue1}" />

<h:outputLabel value="StringValue2:" for="stringValue2" />
<h:selectOneMenu value="#{testBean.stringValue2}" id="stringValue2">
    <f:selectItem itemLabel="null" noSelectionOption="true" />
    <f:selectItem itemLabel="String1" itemValue="String1" />
    <f:selectItem itemLabel="String2" itemValue="String2" />
</h:selectOneMenu>

<h:outputLabel value="IntegerValue:" for="integerValue" />
<h:selectOneMenu value="#{testBean.integerValue}" id="integerValue">
    <f:selectItem itemLabel="null" noSelectionOption="true" />
    <f:selectItem itemLabel="Integer1" itemValue="1" />
    <f:selectItem itemLabel="Integer2" itemValue="2" />
</h:selectOneMenu>

<h:commandButton id="save" action="#{testBean.save}" value="Save" />
...

For all components and values we have the same behavior. If you select the null value and submit the form, JSF will redisplay the old value and not the submitted value.

ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented wemu said: I've used the patch above and the described issue disappears. I've only tested it with inputText components, if I stumble across a selectMenu i'll try that out too.

ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented rogerk said: Did you mean "true" for javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL context param? When it is "false", there is no problem.

ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented wemu said: yes that is written in the description and also true in my environment.

meanwhile: I tried mojarra 2.1.6 and I cannot reproduce this issue there. Although the patch here was not added something else must have changed.

ren-zhijun-oracle commented 12 years ago

@javaserverfaces Commented @BalusC said: Yes, I meant to write true, sorry for the confusion. I can't edit the original ticket anymore.

Another, maybe better, way to fix this issue is to alter UIInput#getSubmittedValue():

public Object getSubmittedValue() {
    if (submittedValue == null && !isValid() && considerEmptyStringNull(FacesContext.getCurrentInstance())) {
        return "";
    }
    else {
        return submittedValue;
    }
}

This way the component libraries which rely on UIInput doesn't need to change their renderers.

ren-zhijun-oracle commented 11 years ago

@javaserverfaces Commented rogerk said: See specification issue: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-939

ren-zhijun-oracle commented 11 years ago

@javaserverfaces Commented cagatay_civici said: considerEmptyStringNull must be considered, without it the initial proposed patch will fail for a case like;

<h:inputText id="name" value="#{bean.input}" />

<h:inputText id="sname" value="#{bean.input2}" required="true" />

<h:commandButton id="btn" value="Submit" />

If name is cleared and form is submitted, validation error happens because of sname field but name still displays "input" model value.

I haven't tested Balusc's improved patch in last comment.

ren-zhijun-oracle commented 11 years ago

@javaserverfaces Commented cagatay_civici said: The patch I added to PrimeFaces is;

if(component instanceof EditableValueHolder) {
EditableValueHolder input = (EditableValueHolder) component;
Object submittedValue = input.getSubmittedValue();

if(ComponentUtils.considerEmptyStringAsNull(context) && submittedValue == null && context.isValidationFailed()) {
    return null;
}
else if(submittedValue != null) {
    return submittedValue.toString();
}
}

So we need to check if another input or current input itself caused validation error as well.

ren-zhijun-oracle commented 7 years ago

@javaserverfaces Commented This issue was imported from java.net JIRA JAVASERVERFACES-2262

ren-zhijun-oracle commented 11 years ago

@javaserverfaces Commented Marked as won't fix on Thursday, November 1st 2012, 9:51:07 am