JSF 2 - Bean Validation: validation failed -> empty values are replaced with last valid values from managed bean
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 2262.