JSF Bean Validation (JSR 303) Quick Tutorial

There are two type of validation available to Java EE applications. As stated in the [1], most of the tedious error checking and error handling is done outside of the model tier. Validators are usually instance of the javax.faces.validator.Validator. Validation normally happen early during the Process Validations phase of the request processing life-cycle. The following validation are possible
  • View/Page validation
  • Model validation
Page level validation is the requirement of the user interface. Cross field validation is the most important. For example, without filling address line one, you cannot start to fill the address line 2. Sometimes, you need to accept the declaration or term and conditions before the submit. The new feature of new days web submit is verification code to avoid denial of attacks. Page level validations are change page to page. Model validation is important to execute business functionality on consistent model. Model is composed by number of Java beans (POJOs, or JPA entities). Model constraints are not allowed to violated via page input by the users. Models can have two states, either "valid" or "invalid".

In JSF well support this paradigm from its life-cycle. It is not allowed to leave the current page in when validations are failed (as a best practice), and error message are possible to display for each and every input separately. Important different between model is that model constraints are not change page to page or even tier to tier. Same model constraints are valid across the tiers presentation to persistence.  Therefore, always, same validation code for model has rewritten for different tiers in the application architecture because model validation is a responsibility of that tire.

Bean validation is very wise approach to model validation because this approach moves the bean validation constraints to bean where those constraints are belongs to. Validating individual beans guarantee the validation of the complete model which is composed from those beans.  This approach avoid the recurring logic for model validation. The JSF 2.0 is rich with the bean validation. Bean validation is injected to the JSF life-cycle. JSF page;

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>New Employee</title>
</h:head>
<h:body>
 <h:messages></h:messages>
 <h:form id="newEmployee">
  <h:panelGrid columns="2">
   <h:outputLabel value="First Name"/>
   <h:inputText value="#{bean.employee.firstName}"/>
   <h:outputLabel value="Last Name"/>
   <h:inputText value="#{bean.employee.lastName}"/>
   <h:outputLabel value="Email"/>
   <h:inputText value="#{bean.employee.email}"/>
  </h:panelGrid>
  <h:commandButton value="Add" action="#{bean.doAddEmployee}"/>
 </h:form>
</h:body>
</html>
The backing bean as follows
package com.oj.example.controller;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import com.oj.example.employee.Employee;

@ManagedBean(name="bean")
@SessionScoped
public class EmployeeController{
 Employee employee ;
 
 public Employee getEmployee() {
  return employee;
 }

 public void setEmployee(Employee employee) {
  this.employee = employee;
 }
 
 public void doAddEmployee(){
  
 }
 
 @PostConstruct
 public void init(){
  employee = new Employee();
 }
}

In this example, treat Employee as entity. Enity is a detached object when it is out of the persistence context.
package com.oj.example.controller;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import com.oj.example.employee.Employee;

@ManagedBean(name = "bean")
@SessionScoped
public class EmployeeController {
	Employee employee;

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public void doAddEmployee() {

	}

	@PostConstruct
	public void init() {
		employee = new Employee();
	}
}

The important point is the @Email annotation, this is the email bean validation tag. Let's see the code for the tag first.
package com.oj.example.beanvalidators;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy=EmailConstraintValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)

public @interface Email {
	String message() default "";
	Class<?>[] groups() default{};
	Class<? extends Payload>[] payload() default {};
}

The class EmailConstraintValidator is the validator implementation. To keep the stuff simple, this code just check whether the '@' sign is exist or not in the email.

package com.oj.example.beanvalidators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class EmailConstraintValidator implements
		ConstraintValidator<Email, String> {

	@Override
	public void initialize(Email email) {

	}

	@Override
	public boolean isValid(String value, ConstraintValidatorContext context) {
		if (-1 == value.indexOf("@"))
		return false;
		else return true;
	}
}
This application is deployed in Glassfish 3. Hibernate bean validation reference implementation is already available in the Glassfish. See the output,



Comments

Popular posts from this blog

How To: GitHub projects in Spring Tool Suite

Spring 3 Part 7: Spring with Databases

Parse the namespace based XML using Python