JSF делает это в методе UIInput#validateValue()
. Он просто вызывает ваш валидатор внутри блока try-catch
, перехватывает ValidatorException
, извлекает из него FacesMessage
и, наконец, добавляет его к FacesContext
идентификатору клиента компонента.
Реализации JSF с открытым исходным кодом. В исходном коде Mojarra 2.1.3 вы можете найти следующее, начиная со строки 1143 класса UIInput
:
// If our value is valid and not empty or empty w/ validate empty fields enabled, call all validators
if (isValid() && (!isEmpty(newValue) || validateEmptyFields(context))) {
if (validators != null) {
Validator[] validators = this.validators.asArray(Validator.class);
for (Validator validator : validators) {
try {
validator.validate(context, this, newValue);
}
catch (ValidatorException ve) {
// If the validator throws an exception, we're
// invalid, and we need to add a message
setValid(false);
FacesMessage message;
String validatorMessageString = getValidatorMessage();
if (null != validatorMessageString) {
message =
new FacesMessage(FacesMessage.SEVERITY_ERROR,
validatorMessageString,
validatorMessageString);
message.setSeverity(FacesMessage.SEVERITY_ERROR);
} else {
Collection<FacesMessage> messages = ve.getFacesMessages();
if (null != messages) {
message = null;
String cid = getClientId(context);
for (FacesMessage m : messages) {
/* Here --> */ context.addMessage(cid, m);
}
} else {
message = ve.getFacesMessage();
}
}
if (message != null) {
/* And here --> */ context.addMessage(getClientId(context), message);
}
}
}
}
}