Validation in JSF

Why is Data Validation required?

Computer application (Web based or otherwise) rely on correct and useful data and therefore data validation is built into systems to ensure that the business logic operates on clean, correct and useful data. Data validation is implemented using functions or routines that check for correctness, meaningfulness, and security of data that are input to the system.

Along with data validation, it is also equally important to look into "Usability" aspect of the validation i.e. how validation errors are handled and displayed back to the user(Usability is a vast topic and we are just talking about the error handling part of it here).

Validation in JSF

JSF lifecycle: 

As you are probably already aware that in JSF world everything is governed by JSF lifecycle, so it's important to understand where and how in the JSF lifecycle validation happens.
 jsf life cycle
<image courtesy www.developersbook.com>

Validation is 3rd phase in life cycle, i.e. after the component object model is built (or restored) and the submitted form fields values are updated in the corresponding components, validation routines (jsf in-built and custom both) are executed. Any validation error at this stage causes the control to jump directly to the "Render Response" phase i.e. processing of "Update Model Values" and "Invoke Application" is skipped.

Lets see how validation is done in JSF.

JSF supports both Declarative and Imperative means of validations

      1.  Declarative

             *  Using JSF standard validators
             *  Using Bean validation -- JSR 303

      2.  Imperative

             *  Validation Method in backing bean
             *  Custom validator by implementing javax.faces.validator.Validator and annotating the class with @FacesValidator

Declarative Validation using JSF tags 

Validator Class Tag Function
BeanValidator validateBean Registers a bean validator for the component.
DoubleRangeValidator validateDoubleRange Checks whether the local value of a component is within a certain range. The value must be floating-point or convertible to floating-point.
LengthValidator validateLength Checks whether the length of a component’s local value is within a certain range. The value must be a java.lang.String.
LongRangeValidator validateLongRange Checks whether the local value of a component is within a certain range. The value must be any numeric type or String that can be converted to a long.
RegexValidator validateRegEx Checks whether the local value of a component is a match against a regular expression from the java.util.regex package.
RequiredValidator validateRequired Ensures that the local value is not empty on an javax.faces.component.EditableValueHolder component.
 
Each of the above validator implementations have a corresponding tag available in JSF base reference implementation. Apart from above tags, the most commonly used form validation "Required" i.e. the form field cannot be empty, user must provide some information, is implemented in JSF as an attribute "Required". This attribute is available in all tags that extend EditableValueHolder namely inputText,teaxtArea, Select, Menu etc.

Lets look at some examples of declarative validation using tags and for that refer to index.xhtml

1)  Required Field


<h:outputLabel for="fName" value="*Enter First Name: " title="First Name"/>
<h:inputText id="fName" value="#{personView.per.fName}" title="First Name" tabindex="1" required="true" 
requiredMessage="first name is required"/>
<h:message id="m1" for="fName" style="color:red"/> <p></p>
Setting attribute required="true" makes field mandatory, i.e. if user submits form without providing first name, a message as defined by attribute requiredMessage="first name is required" is displayed to the user.
Note: The default value of "required"this attribute is "false", so if this attribute is not present then the field in NOT mandatory.

 2) DoubleRangeValidator

This tag is used to validate a floating point range.
<h:outputLabel for="ustaRankingId" value="Enter USTA Ranking: " title="USTA Ranking"/>
<h:inputText id="ustaRankingId" value="#{personView.ustaRanking}" title="USTA Ranking" tabindex="8" 
   size="3" validatorMessage="Registration Open Only for Level 3.0 to 4.5">
  <f:validateDoubleRange minimum="3.0" maximum="4.5" for="ustaRankingId"/>
  <!--f:validateRegex pattern="[3-4]\.?[05]" for="ustaRankingId"/-->
</h:inputText>
<h:message id="m6" for="ustaRankingId" style="color:red"/> <p></p>
Attributes minimum="3.0" maximum="4.5" validate that the value of this form field is between float 3.0 and 4.5. Now this filed is not designated as required="true", so its not mandatory for user to provide value, however, when a value is provided, the doubleRangeValidator ensures that the value is between 3.0 and 4.5, else a message as defined by attribute validatorMessage="Registration is Open....." is displayed to the user.

... other JSF validation tags follow/work on similar pattern and so lets move on to other types of validation supported in JSF.

Declarative Validation using Bean Validation -- JSR 303

JSR 303 is implemented by JSF framework (and other like Spring and Hibernate) and supports validation using annotations in the bean. A good reason to use this feature is that it is "display framework/ technology" agnostic and provides a centralized location for bean constraints and validation as compared to being scattered across front-end and app-tier.
Lets look at some examples of JSR 303 validation and for that refer to index.xhtml and Person.java.

In index.xhtml, there is a field for "Sex" options - Male or Female and we want to make this field required, i.e. user should select one of the two option (when the form is first displayed, neither option is selected); the JSF code is very straight forward, there is NO validation/checks done.
<h:outputLabel for="sexId" value="*Sex:" title="Sex"/>
<h:selectOneRadio id="sexId" value="#{personView.per.sex}" title="Sex" tabindex="5">
  <f:selectItem itemLabel="M" itemValue="M" />
  <f:selectItem itemLabel="F" itemValue="F" />
  <f:validateBean disabled="false"/>
</h:selectOneRadio>
<h:message id="m3" for="sexId" style="color:red"/> <p></p>
The "Required" constraint is added declaratively in Person.java using annotation @NotNull corresponding to property sex, as follows:
  @NotNull(message = "Please select Sex Type, (M) for Male or (F) for Female")
  String sex;
@NotNull makes field mandatory, i.e. if user submits form without selecting radio button corresponding to either of the (M) or (F) option then a message as defined by attribute message="Please select....." is displayed to the user.. 


Imperative Validation

The simple declarative validation discussed so far is a good first step but is rarely sufficient. Most enterprise applications require more complex validation logic that can span multiple properties, multiple entities, security-roles and hence require custom code. Imperative validations is also called as application level validation.
In JSF world application level validation can be done either by
1) Implementing interface javax.faces.validator.Validator and annotating that class with @FacesValidator 
2) Implementing validation in a backing bean method.
    or
3) Using Custom Component

In this article, we will focus on the first two ways of validation.

Custom Validator

A java class as validator needs to 
  1. be annotated with @FacesValidator.The presence of this annotation on a class automatically registers the class with the runtime as a Validator.
  2. implement javax.faces.validator.Validator
for example refer to EmailValidator.java in attached source.

@FacesValidator("emailValidator")
public class EmailValidator implements Validator

The implementation is very straight forward; Validator interface has a method
validate(FacesContext context, UIComponent component, java.lang.Object value)
This method needs to be implemented by the validator class. All the validation logic goes in this method (or say its the entry point).
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    log("Validating submitted email -- " + value.toString());
    matcher = pattern.matcher(value.toString());
    
    if (!matcher.matches()) {
      FacesMessage msg =
              new FacesMessage(" E-mail validation failed.",
              "Please provide E-mail address in this format: abcd@abc.com");
      msg.setSeverity(FacesMessage.SEVERITY_ERROR);
    
      throw new ValidatorException(msg);
    }
  }
JSF framework automatically calls this method at appropriate time in the life-cycle. If the custom validation logic fails, then this method exits by throwing a ValidatorException(msg) where "msg" is an instance of javax.faces.application.FacesMessage, which is queued in the messages list and displayed to the user; else If the logic succeeds then the code exits normally.

Custom validator is integrated/used in the xhtml by using <f:validator> jsf tag.(refer to index.xhtml)
<h:outputLabel for="email" value="*Enter Email: " title="Primary Email"/>
<h:inputText id="email" value="#{personView.per.email}" required="true" requiredMessage="email is required"  
title="Primary Email" tabindex="3"> 
  <f:validator validatorId="emailValidator" />
</h:inputText>
<h:message id="m2a" for="email" style="color:red"/> <p></p>
Note that the value of the attribute validatorId is the bind id of the custom validator class.(refer to EmailValidator.java)
@FacesValidator("emailValidator")

Validation using a Method in Backing Bean

A method in the backing bean can serve as a validation method if it confirms to the following signature:
public void someMethod(FacesContext context, UIComponent component, java.lang.Object value){ .. }
if you notice, the method signature is same as that of "validate" method of custom Validator, except that the method name is NOT confined to "validate", it can be any valid java method name.(refer to PersonView.java)
Note: this example refers to multiple bean properties for validation
/**
 *
 * Validation method 3
 */
public void validatePlayer3(FacesContext context, UIComponent component, Object value) throws ValidatorException {
  String selectedRadio = (String) value;
  String msg = "V3-- Since you indicated that you play Tennis, Please enter Club Name.";
  String clubNameFromComp = (String) clubNameBind.getSubmittedValue();
  log("\n\t ##clubName=" + clubNameFromComp + ",##selectedRadio=" + selectedRadio + "##\n\t");
  if ((clubNameFromComp == null || "".equalsIgnoreCase(clubNameFromComp)) && "Y".equalsIgnoreCase(selectedRadio)) {
    throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
  }
}
JSF framework automatically calls this method at appropriate time in the life-cycle. If the custom validation logic fails, then this method exits by throwing a ValidatorException(msg) where "msg" is an instance of javax.faces.application.FacesMessage, which is queued in the messages list and displayed to the user; else If the logic succeeds then the code exits normally.
Custom validator is integrated/used in the xhtml by using validator attribute; the value of this attribute is EL expression corresponding to the backing bean method which implements the validation logic.(refer to index.xhtml)
<h:outputLabel for="sportsPer" value="Do You Play Tennis?" title="Play tennis"/>
  <h:selectOneRadio id="sportsPer" value="#{personView.per.likesTennis}" 
     validator="#{personView.validatePlayer3}" title="Play tennis" tabindex="6">
    <f:selectItem itemLabel="Yes" itemValue="Y" />
    <f:selectItem itemLabel="No" itemValue="N" />
    <!--f:attribute name="clubNameAttr" value="# {clubNameBind.submittedValue}" /-->
  </h:selectOneRadio>
<h:message id="m4" for="sportsPer" style="color:red"/> <p></p>
There are 3 variants of validation methods in PersonView.java, each has a different approach (in conjunction with index.xhtml) for getting data to validate.

This completes our Section on what and how to validate, now moving on to how validation messages are displayed to user.
JSF provides two tags for displaying messages (which are queued  either by jsf validation tags or custom validators)
1.  h:message, contains message specific to a component.It is a good practice to have <h:message> right after the component tag for which the message is queued.
2.  h:messages, messages from all components and all other messages queued in by the system.

see index.xhtml,for how the above tags are used.

Form Validation and Usability

As I mentioned earlier in the blog that along with form validation, it is equally important to display correct message as well. There is also an increased awareness in the technology world about developing application that are accessible to people with visual and other disabilities. One of the major stumbling block in usability is form validation and how to recover from it. User's with disability quite often use some sort of tool like JAWS, to read/interpret a web page. The application we code should take into account how, these tools read/interpret our pages and what best we can do to accommodate ADA needs.Here are some suggestion which I consider are good practices and we developers should at the minimum include in our application:

  1. If form validation fails, tell user that the form validation failed and list all the instructions/errors at the top of form.
  2. Repeat the instructions in front/after the field.
  3. If possible set focus on the "top" error message or on the field corresponding to the first error message.
  4. Use correct font color and size for displaying error.
  5. The error message should tell the user what needs to be done and NOT what is wrong.
  6. Use correct tab index or make sure that form fields are in a logical tab order
  7. When form controls are text input fields use the LABEL element.
  8. Check to make sure the page does not contain a strobe effect
  9. Make sure the page does not contain repeatedly flashing images
JSF and Accessibility support is evolving and some vendors provide some support. Refer to index.xhtml for how message display can be done (although is far from accessibility compliant, its a start)
<ui:param name="errorMessages" value="#{facesContext.getMessageList()}" />
  <h:panelGroup rendered="#{not empty errorMessages}" styleClass="errorMsg">
  <h:outputText value="Form Submission was not successful; Please review and correct listed errors and then resubmit " 
      escape="false"/>
  <br />
  <h:messages style="color: red" globalOnly="false"/>
</h:panelGroup>

you can download the source from here

Hope this blog helped you in gaining understanding of the validation in JSF. If you have any question orsuggestion, please post your comment.

Prasanna Bhale

22 comments:

  1. Thanks you, Prasanna Bhale! The post helped me to understand a little more about JSF Validation. I have one question, if form validation have passed, but occurs business exception on action method of the ManagedBean, which is the practice used?
    Regards

    ReplyDelete
    Replies
    1. Considering that your backing bean is at least ViewScoped, so that submitted form data can be displayed back to user; I would create FacesMessage for the business exception and display it in < h:messages >
      public void formSub() {
      try {
      // ... business logic exception
      } catch(RegistrationFullException ex) {
      FacesMessage msg =
      new FacesMessage("Registration is full for now! Please check back later.");
      msg.setSeverity(FacesMessage.SEVERITY_ERROR);
      FacesContext.getCurrentInstance().addMessage("", msg);
      }
      }

      Delete
  2. It's an awesome explanation. I got a clear cut idea with this stuff. Thank you very much.

    ReplyDelete
  3. The source code is missing the index.xhtml. Can you please include it.

    ReplyDelete
  4. Excellent summary on different validation options within JSF. Thanks a lot for it!

    ReplyDelete
  5. Thanks for this amazing article. Things are very well explained :)

    ReplyDelete
  6. please follow your software :- The Validation Change Management for manufacture somewhere else the website manufacturing sprint is by method of the end of it be supposed to be Validation Software solution big quantity in prevalent way Validation Software the meaning of reformation which will produce put down the blame on new belongings. The Electronic Validation necessities in adding collectively to the possessions will pipe up lends a hand in the most new thing which has occurred.

    ReplyDelete
  7. The article was excellent, JSF, Data validation is implemented using functions or routines that check for correctness, meaningfulness, and security. For more information.
    Check this site tekslate for indepth Jsf-tutorials
    Go here if you’re looking for information on jsf-tutorials

    ReplyDelete
  8. The article was excellent, JSF, Data validation is implemented using functions or routines that check for correctness, meaningfulness, and security. For more information.
    Check this site tekslate for indepth Jsf-tutorials
    Go here if you’re looking for information on jsf-tutorials

    ReplyDelete
  9. Hey man, thx for your post, it helps me a lot.

    ReplyDelete
  10. I'd like too validate (with own validator) some fields that are not required (validation only if it is filled) but my validator is only called when required attribute is true, not else.

    ReplyDelete
  11. Hey thanks for this great article. For preparing JSF interview, here is an article on JSF Interview Questions with Answers

    ReplyDelete
  12. Thank you very much for the nice tutorial :) it tested the source code and worked like a charm. I just have to add the "@Model" annotation to the Person class after I got this error: "Exception while loading the app : CDI deployment failure:WELD-001408: Unsatisfied dependencies for type Person with qualifiers @Default". Thanks again!

    ReplyDelete
  13. Thanks for the very easy to understand tutorial!

    ReplyDelete
  14. Wow.... i'm very grateful to you for this tutorial.

    ReplyDelete
  15. "I like your post it is too good
    for more information visit Intellipaat"

    ReplyDelete
  16. Great site for these post and i am seeing the most of contents have useful for my Carrier.Thanks to such a useful information.Any information are commands like to share him.
    PEGA Training in Chennai

    ReplyDelete