JSF Validations

Using JSF Standard Built-in Validations
JSF provides built-in support for validations of input component tags. You can supply it a attribute required=”true” which will check if a value is supplied or not. There are built-in validators which you can nest in all JSF input tags.

Below are the built-in Validators –

  1. f:validateDoubleRange
  2. f:validateLongRange
  3. f:validateLength

One should be cautious as when the required attribute is not set and user supplies a blank input, then no validation are performed.

Below is a example of using JSF Validator –

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<title>JSF Validations Example Form</title>
</head>
<body>
<f:view>
<h2>JSF Validations Example Form</h2>
<h:form id="helloForm">

<ul>
<li><h:outputText value="Enter your name :" /> <br />
<t:message id="usernameMessage" for="username" style="color:red;" /> <br />
<h:inputText value="#{userBean.name}" id="username" required="true" />
</li>
</ul>
<h:commandButton action="#{userBean.sayHello}" value="Enter" />
</h:form>
</f:view>
</body>
</html>

When user does not supply value for username –

jsf14

Creating a Custom Validator
JSF also provides support for writing your own custom Validators. Below are the steps which you would need to do in order to write your own custom validator. I am writing a custom validator for verifying a email address using commons-validator.

Step 1:
Implement interface, javax.faces.validator.Validator

package com.test.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class EmailValidator implements Validator {
	public void validate(FacesContext facesContext, UIComponent component, Object object)
			throws ValidatorException {
		org.apache.commons.validator.EmailValidator instance = org.apache.commons.validator.EmailValidator.getInstance();
		if(!instance.isValid(object.toString())){
			FacesMessage facesMessage = new FacesMessage("Invalid email address");
			throw new ValidatorException(facesMessage);
		}
	}
}

Step 2:

Register above validator in faces-config.xml.


<validator>
	<description></description>
	<display-name>EmailValidator</display-name>
	<validator-id>EmailValidator</validator-id>
	<validator-class>com.test.validator.EmailValidator</validator-class>
</validator>

Step 3:

Use above registered validator in your page –


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<title>JSF Validations Example Form</title>
</head>
<body style="font:Arial 12px;">
<f:view>
	<h2>JSF Validations Example Form</h2>
	<h:form id="helloForm">

		<ul>
			<li><h:outputText value="Enter email :" /> <br />
			<t:message id="emailMessage" for="email" style="color:red;" /> <br />
			<h:inputText value="#{userBean.email}" id="email" required="true">
				<f:validator validatorId="EmailValidator"></f:validator>
			</h:inputText> 
			</li>
		</ul>
		<h:commandButton action="#{userBean.sayHello}" value="Enter" />
	</h:form>
</f:view>
</body>
</html>

Output:

jsf2

Interdependant Fields Validation using Custom Validator

Though not a perfect example for dependant field validation, I couldn’t come up with any other in short time, we have a check box [are you married?] which when selected then marriage date should be valid.

I have created a custom validator for Date which I am using here –


package com.test.validator;

import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

public class MarriedDateValidator extends DateValidator {
	
	@Override
	public void validate(FacesContext facesContext, UIComponent component,
			Object object) throws ValidatorException {
		UIInput input = (UIInput) component.findComponent("married");
		if(input.isValid()){
			if(input.getValue().toString().equals("true")){
				super.validate(facesContext, component, object);
			}
		}
	}
}
 

If you notice line where I get access to the input component component.findComponent(“married”); and then uses it for further decisions on validations.

Just for reference – below is the class DateValidator.


package com.test.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class DateValidator implements Validator {

	public void validate(FacesContext facesContext, UIComponent component, Object object)
			throws ValidatorException {
		org.apache.commons.validator.DateValidator instance = org.apache.commons.validator.DateValidator.getInstance();
		if(!instance.isValid(object.toString(), "dd/MM/yyyy", true)){
			FacesMessage facesMessage = new FacesMessage("Invalid date");
			throw new ValidatorException(facesMessage);
		}
	}

}

The next step is to define above in faces-config.xml.


<validator>
	<description></description>
	<display-name>MarriedDateValidator</display-name>
	<validator-id>MarriedDateValidator</validator-id>
	<validator-class>com.test.validator.MarriedDateValidator</validator-class>
</validator>

And then using it in your page –


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<title>JSF Validations Example Form</title>
</head>
<body style="font:Arial 12px;">
<f:view>
	<h2>JSF Validations Example Form</h2>
	<h:form id="helloForm">
		<ul>
			<li><h:outputText value="Are you married? :" /> <h:selectBooleanCheckbox value="#{userBean.married}" id="married" /> <br />
			<h:outputText value="Enter marriage date :" /> <br />
			<t:message id="domMessage" for="dom" style="color:red;" /> <br />
			<h:inputText value="#{userBean.dateOfMarriage}" id="dom">
				<f:validator validatorId="MarriedDateValidator"></f:validator>
			</h:inputText>
			</li>
		</ul>
		<h:commandButton action="#{userBean.sayHello}" value="Enter" />
	</h:form>
</f:view>
</body>
</html>


In above notice that there is no required=”true” for the userBean.dateOfMarriage input tag. When the check box is not selected no validations are performed on the field.

jsf3

Only when the checkbox is selected, validations are performed and you get following message –

jsf4

Creating Custom Converters

A custom converter is called after custom validations are performed and any errors during conversion step, the errors are displayed in the same input page while all orignal input values are retained.

The good thing about convertors is unlike a validator which is only called when required=”true” is set for the input tag, it gets called even if the input field is having a empty value.

We can use this to handle validations of non mandatory fields where if the user enters the data then it should be valid. For eg. We are having a field “Date Of Joining” which is not a mandatory field, but if user enters a value we want it to be a valid date.

Below are the steps on writing a custom converters –

Step 1:

Implement a interface, javax.faces.convert.Converter.


package com.test.converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class DateConverter implements Converter {

	public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String val)
			throws ConverterException {
		String pattern = "dd/MM/yyyy";
		boolean required = ((UIInput)uiComponent).isRequired();
		if((val==null || val.trim().isEmpty()) &amp;&amp; !required )
			return null;
		org.apache.commons.validator.DateValidator instance = org.apache.commons.validator.DateValidator.getInstance();
		if(!instance.isValid(val.toString(), pattern, true)){
			FacesMessage facesMessage = new FacesMessage("Using Converter - Invalid date");
			throw new ConverterException(facesMessage);
		}		
		try {
			return new SimpleDateFormat(pattern).parse(val);
		} catch (ParseException e) {
			FacesMessage facesMessage = new FacesMessage("Using Converter - Invalid date");
			throw new ConverterException(facesMessage);
		}
	}

	public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object val)
			throws ConverterException {
		return val.toString();
	}

}

Please note following –

boolean required = ((UIInput)uiComponent).isRequired(); – Using this we can check if the field was required or not. Based on it we can either ignore the conversion or perform it.

Step 2:

The next step is registering this convertor in faces-config.xml.


	<converter>
		<display-name>DateConverter</display-name>
		<converter-for-class>java.util.Date</converter-for-class>
		<converter-class>com.test.converter.DateConverter</converter-class>
	</converter>

The JSF will call our converter when it finds the type of field in a bean as java.util.Date.

Below is our UserBean.java


package com.test.beans;

import java.util.Date;

import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import com.test.validator.DateValidator;

public class UserBean {

	private Date dateOfJoining;

	public Date getDateOfJoining() {
		return dateOfJoining;
	}

	public void setDateOfJoining(Date dateOfJoining) {
		this.dateOfJoining = dateOfJoining;
	}


	public String sayHello() {
		return "hello";
	}
}


Step 3:

As you have mapped the converter for Date classes you don’t need to specify anything in page –


<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>
<html>
<head>
<title>JSF Validations Example Form</title>
</head>
<body>
<f:view>
	<h2>JSF Validations Example Form</h2>
	<h:form id="helloForm">

		<ul>
			<li><h:outputText value="Enter date of joining :" /> <br />
			<t:message id="dojMessage" for="doj" style="color:red;" /> <br />
			<h:inputText value="#{userBean.dateOfJoining}" converterMessage="Please enter valid date of joining" id="doj" />
			</li>
		</ul>
		<h:commandButton action="#{userBean.sayHello}" value="Enter" />
	</h:form>
</f:view>
</body>
</html>

Notice that the required=”true” is not set and you can specify your own custom message to be shown in case of conversion error by using converterMessage.

Output:

jsf5




Comments

  1. PeterNo Gravatar June 19th

    Comment Arrow

    Hi Shiv!

    FYI:
    JSF Validation with MyFaces Extensions Validator is more powerful and quite easy to use.


  2. MattNo Gravatar June 24th

    Comment Arrow

    The section “Creating Custom Converters” opens with the sentence “A converter is called after validations…”. It is in fact the other way round. If it can’t convert then it can’t validate.


  3. shivNo Gravatar June 25th

    Comment Arrow

    Thanx @Matt for pointing out the error. I agree that the implicit JSF conversions [like converting to numeric..] happen before the validations, but I observed that the custom converters are called after custom validators. Please correct me if I am wrong.


  4. rajuNo Gravatar July 23rd

    Comment Arrow

    Thanks for providing this information….I need how to use renderkit,referencedbean amd factory tag used in faces-config.xml


  5. jokerNo Gravatar December 21st

    Comment Arrow

    nice example…tks


Add Yours

  • Author Avatar

    YOU


Comment Arrow




About Author

shiv

This author has not yet written a description. Please give them some time to get acquainted with the site and surely they will write their masterpiece.