For example: I have a JSF Validator to validate e-mail thusly:
@FacesValidator(value="validateEmail")
public class Email implements Validator
{
private static final String EMAIL_REGEXP =
"^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
@Override
public void validate(FacesContext context, UIComponent c, Object val) throws ValidatorException
{
String email = (String) val;
Pattern mask = null;
mask = Pattern.compile(EMAIL_REGEXP);
Matcher matcher = mask.matcher(email);
if (!matcher.matches()) {
FacesMessage message = new FacesMessage();
message.setDetail("Must be of the form xxx@yyy.zzz");
message.setSummary("E-mail Addresss not valid");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
This validator will throw an exception if the user doesn’t enter an e-mail. However sometimes I want to make the e-mail an optional field. Is there a way to do this that doesn’t require me to write a different validator?
Ideally I would like it to check for a parameter somewhere in the JSF markup that uses it.
To answer your concrete question, you can make use of
<f:attribute>which is enclosed in the same component.Inside the
validate()method it’s available byUIComponent#getAttributes()of the 2ndUIComponentargument.The better solution in your particular case, however, is just to let the validator
returnwhen the value is null or empty.In JSF 1.x this would not be necessary because validators wouldn’t be called when the input is null or empty. But in JSF 2.x this has changed in order to support JSR303 bean validation. So if you want to skip validation on empty fields, you’d need to check this in every single JSF
Validator.Note that when you have this in your
web.xmlthen you can safely omit the
email.isEmpty()part from the check because it would always benullinstead of an empty string.Unrelated to the concrete problem, the pattern which you’ve there is outdated. These days unicode characters are allowed in email addresses.
(note that
^and$are unnecessary becausePatternimplicitly uses this already)Further I also suggest to do the
Pattern#compile()directly on astatic finalvariable. Compiling a pattern is relatively expensive and aPatterninstance is threadsafe anyway.