Custom JSF validator for required fields
<?xml version='1.0'?>
<facelet-taglib version='2.0' ... >
<namespace>http://ip.client/ip-jsftoolkit/validator</namespace>
<tag>
<tag-name>requiredFieldValidator</tag-name>
<validator>
<validator-id>ip.client.jsftoolkit.RequiredFieldValidator</validator-id>
</validator>
<attribute>
<description>Resource bundle name for the required message</description>
<name>bundle</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description>Key of the required message in the resource bundle</description>
<name>key</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description>Label string for the required message</description>
<name>label</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
</tag>
</facelet-taglib>
We defined three attributes in order to achieve a high flexibility. A simple using would be
<h:outputLabel for='myInput' value='#{text['myinput']}'/>
<h:inputText id='myInput' value='...'>
<jtv:requiredFieldValidator label='#{text['myinput']}'/>
</h:inputText>
The validator class itself is not difficult. Dependent on the ‘ key’ parameter (key of the required message) and the ‘ label’ parameter (text of the corresponding label) there are four cases how the message gets acquired.
/**
* Validator for required fields.
*/
@FacesValidator(value = RequiredFieldValidator.VALIDATOR_ID)
public class RequiredFieldValidator implements Validator
{
/** validator id */
public static final String VALIDATOR_ID = 'ip.client.jsftoolkit.RequiredFieldValidator';
/** default bundle name */
public static final String DEFAULT_BUNDLE_NAME = 'ip.client.jsftoolkit.validator.message';
private String bundle;
private String key;
private String label;
@Override
public void validate(FacesContext facesContext,
UIComponent component, Object value) throws ValidatorException
{
if (!UIInput.isEmpty(value)) {
return;
}
String message;
String bundleName;
if (bundle == null) {
bundleName = DEFAULT_BUNDLE_NAME;
} else {
bundleName = bundle;
}
if (key == null && label == null) {
message = MessageUtils.getMessageText(
MessageUtils.getResourceBundle(facesContext, bundleName),
'jsftoolkit.validator.emptyMandatoryField.1');
} else if (key == null && label != null) {
message = MessageUtils.getMessageText(
MessageUtils.getResourceBundle(facesContext, bundleName),
'jsftoolkit.validator.emptyMandatoryField.2', label);
} else if (key != null && label == null) {
message = MessageUtils.getMessageText(
MessageUtils.getResourceBundle(facesContext, bundleName), key);
} else {
message = MessageUtils.getMessageText(
MessageUtils.getResourceBundle(facesContext, bundleName), key, label);
}
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_WARN, message, StringUtils.EMPTY));
// getter / setter
...
}
}
MessageUtils is an utility class to get ResourceBundle and message text. We also need two text in the resource bundle (property file)
jsftoolkit.validator.emptyMandatoryField.1=Some required field is not filled in.
jsftoolkit.validator.emptyMandatoryField.2=The required field '{0}' is not filled in.
and the following context parameter in web.xml
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>true</param-value>
</context-param>
This solution is not ideal because we need to define the label text (like #{text[‘myinput’]}) twice and to attach the validator to each field to be validated. A better and generic validator for multiple fields will be presented in the next post. Stay tuned!
Reference: Custom JSF validator for required fields from our JCG partner Oleg Varaksin at the Thoughts on software development blog.




