Search

Struts 2 Hibernate Validation Example

The Hibernator Validator framework follows the DRY (Don't Repeat Yourself) principle. Using Hibernator Validator you need to specify the constraints using annotations in the domain object. Once you specify the constraints you can use it in any layer of your application without duplicating it.
Hibernate Validator comes with basic buit-in constraints like @Length(min=, max=), @Max(value=), @Min(value=), @NotNull, @NotEmpty and so on. You can also build your own constraints easily.
In this example you will see how to integrate Struts 2 with Hibernator Validator using the Full Hibernate Plugin 4 GA.
You need to have all the lib files that we used in the previous example ( Struts 2 Hibernate Integration ).
The domain object User, with the validation constraints is shown below.
0package com.vaannila.domain;
0 
0import java.io.Serializable;
0 
0import javax.persistence.Column;
0import javax.persistence.Entity;
0import javax.persistence.GeneratedValue;
0import javax.persistence.Id;
0import javax.persistence.Table;
0 
0import org.hibernate.validator.Length;
0import org.hibernate.validator.NotEmpty;
0 
0@Entity
0@Table(name = "USER")
0public class User implements Serializable {
0 
0private static final long serialVersionUID = 6295524232169619097L;
0 
0private Long id;
0 
0private String name;
0 
0private String password;
0 
0private String gender;
0 
0private String country;
0 
0private String aboutYou;
0 
0private Boolean mailingList;
0 
0@Id
0@GeneratedValue
0@Column(name = "USER_ID")
0public Long getId() {
0return id;
0}
0 
0public void setId(Long id) {
0this.id = id;
0}
0 
0@NotEmpty
0@Length(max=50)
0@Column(name = "USER_NAME", nullable = false, length = 50)
0public String getName() {
0return name;
0}
0 
0public void setName(String name) {
0this.name = name;
0}
0 
0@Length(min=6, max=10)
0@Column(name = "USER_PASSWORD", nullable = false, length = 10)
0public String getPassword() {
0return password;
0}
0 
0public void setPassword(String password) {
0this.password = password;
0}
0 
0@NotEmpty(message="Please select a gender")
0@Column(name = "USER_GENDER")
0public String getGender() {
0return gender;
0}
07 
07public void setGender(String gender) {
07this.gender = gender;
07}
07 
07@NotEmpty(message="Please select a country")
07@Column(name = "USER_COUNTRY")
07public String getCountry() {
07return country;
08}
08 
08public void setCountry(String country) {
08this.country = country;
08}
08 
08@NotEmpty
08@Length(max=100)
08@Column(name = "USER_ABOUT_YOU", length = 100)
08public String getAboutYou() {
09return aboutYou;
09}
09 
09public void setAboutYou(String aboutYou) {
09this.aboutYou = aboutYou;
09}
09 
09@Column(name = "USER_MAILING_LIST")
09public Boolean getMailingList() {
09return mailingList;
10}
1 
1public void setMailingList(Boolean mailingList) {
1this.mailingList = mailingList;
1}
1 
1}
As you can see in addition to the JPA annotations you have the Hibernator Validator constraints.
The @NotEmpty constraint checks if the String is not null or not empty.
The @Length(min=6, max=10) constraint checks whether the lenght is within the min max range.
The validation messages are auto generated by the plug-in. You can also override the default message using the message attribute of the constraint. For gender and country properties we specify a customized message.
@NotEmpty(message="Please select a gender")
@Column(name = "USER_GENDER")
public String getGender() {
return gender;
}

@NotEmpty(message="Please select a country")
@Column(name = "USER_COUNTRY")
public String getCountry() {
return country;
}
In the UserAction class you need to specify the @Valid annotation for the domain object that needs to be validated.
package com.vaannila.web;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.validator.Valid;

import com.opensymphony.xworkActionSupport;
import com.vaannila.dao.UserDAO;
import com.vaannila.dao.UserDAOImpl;
import com.vaannila.domain.User;

public class UserAction extends ActionSupport {

private static final long serialVersionUID = -6659925652584240539L;

@Valid
private User user;
private List<User> userList = new ArrayList<User>();
private UserDAO userDAO = new UserDAOImpl();

public String add()
{      
userDAO.saveUser(user);
return SUCCESS;
}

public String list()
{
userList = userDAO.listUser();
return SUCCESS;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public List<User> getUserList() {
return userList;
}

public void setUserList(List<User> userList) {
this.userList = userList;
}

}
Since we use the Hibernate Plugin you need to extend the package form hibernate-default package. The hibernate-default package has the following three interceptor stacks.

·         basicStackHibernate: Struts2 basickStack + Hibernate session and transaction capability.
·         defaultStackHibernate: Struts2 defaultStack (no validations) + Hibernate validation, session and transaction capability.
·         defaultStackHibernateStrutsValidation: Struts2 defaultStack (with validation) + basicStackHibernate.
The struts configuration file is shown below.
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 0//EN"

<struts>
<package name="default" extends="hibernate-default">
<action name="addUser" method="add"class="com.vaannila.web.UserAction">
<result name="input">/register.jsp</result>
<result name="success" type="redirect">listUser</result>
</action>
<action name="listUser" method="list"class="com.vaannila.web.UserAction">
<interceptor-ref name="basicStackHibernate" />
<result name="success">/register.jsp</result>
</action>
</package>
</struts>
By default the defaultStackHibernate interceptor stack will be used. In the addUser action we use this inteceptor stack since we need validation capability and during the listUser action action we usebasicStackHibernate because we don't need validation capability this time.
In the register.jsp page instead of using the name attribute to specify the property value we use the keyattribute. This is need for the default validation messages to be generated.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 01 Transitional//EN" "http://www.worg/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Page</title>
<s:head />
<style type="text/css">
@import url(style.css);
</style>
</head>
<body>
<s:actionerror/>
<s:form action="addUser">
<s:hidden name="user.id" />
<s:textfield key="user.name" />
<s:password key="user.password" />
<s:select key="user.gender" list="{'Male','Female'}" headerKey=""
headerValue="Select" label="Gender" />
<s:select key="user.country" list="{'India','USA','UK'}" headerKey=""
headerValue="Select" label="Country" />
<s:textarea key="user.aboutYou" />
<s:checkbox key="user.mailingList"
label="Would you like to join our mailing list?" />
<s:submit />
</s:form>


<s:if test="userList.size() > 0">
<div class="content">
<table class="userTable" cellpadding="5px">
<tr class="even">
<th>Name</th>
<th>Gender</th>
<th>Country</th>
<th>About You</th>
<th>Mailing List</th>
</tr>
<s:iterator value="userList" status="userStatus">
<tr
class="<s:if test="#userStatus.odd == true ">odd</s:if><s:else>even</s:else>">
<td><s:property value="name" /></td>
<td><s:property value="gender" /></td>
<td><s:property value="country" /></td>
<td><s:property value="aboutYou" /></td>
<td><s:property value="mailingList" /></td>
</tr>
</s:iterator>
</table>
</div>
</s:if>
</body>
</html>
The key values should be specified in the UserAction.properties file and this file should be saved next to the UserAction.java file.
user.name=User Name
user.password=Password
user.aboutYou=About You
user.mailingList=Mailing List
The default validation messages will be generated using the field labels as prefix.
When you execute the example and submit the form without entering any values you will see the following validation messages.

The validation messge for the fields User Name, Password and About You has the field label before the default validation error message. This is because we specified the key values in theUserAction.properties file. If you only want the validation message to be displayed then don't specify an entry for that field in the properties file. Here the gender and the country fields have only the customized error messages and not the field labels.

No comments:

Post a Comment