Here’s the field:
<h:inputText id="mobilePhoneNo"
value="#{newPatientBean.phoneNo}"
required="true"
requiredMessage="Required"
validator="#{mobilePhoneNumberValidator}"
validatorMessage="Not valid (validator)"
converter="#{mobilePhoneNumberConverter}"
converterMessage="Not valid (converter)"
styleClass="newPatientFormField"/>
And the validator:
@Named
@ApplicationScoped
public class MobilePhoneNumberValidator implements Validator, Serializable
{
@Override
public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException
{
// This will appear in the log if/when this method is called.
System.out.println("mobilePhoneNumberValidator.validate()");
UIInput in = (UIInput) uic;
String value = in.getSubmittedValue() != null ? in.getSubmittedValue().toString().replace("-", "").replace(" ", "") : "";
if (!value.matches("04\\d{8}"))
{
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please enter a valid mobile phone number.", null));
}
}
}
When I press the command button within the form, I get the following behaviour:
- When the field is blank, the message is “Not valid (converter)”.
- When the field has a valid entry, the message is “Not valid (validator)”.
- When the field has an invalid entry, the message is “Not valid (converter)”.
In all three cases, MobilePhoneNumberConverter.getAsObject() is called. MobilePhoneNumberValidator.validate() is never called. And when the field is blank, it ignores the required="true" attribute and proceeds straight to conversion.
I would have thought the proper behaviour would be:
- When the field is blank, the message should be “Required”.
- When the field has a valid entry, there should be no message at all.
- When the field has an invalid entry, the message should be “Not valid (validator)”.
- If, by some chance, validation passed by conversion didn’t, the message should be “Not valid (converter)”.
Note: The backing bean is request scoped, so there’s no fancy AJAX business going on here.
Update:
Might it have something to do with javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL being set to true?
Conversion happens before validation. Converters will also be called when the value is
nullor empty. If you want to delegate thenullvalue to the validators, then you need to design your converters that it just returnsnullwhen the supplied value isnullor empty.Unrelated to the concrete problem, your validator has a flaw. You should not extract the submitted value from the component. It’s not the same value as returned by the converter. The right submitted and converted value is available as the 3rd method argument already.