Sunday, October 30, 2011

Spring MVC Form data validation with Spring-Modules Annotations

this post will guide you how to validate form data based on the annotations provided in the spring-modules framework.In addition, this will show you how to bind form data to a data model and how to use EL(Expression Language) in Spring web application.

the folllowing technologies have been used to prepare this post. 

Spring MVC 3
Maven building tool
Spring Form tag libraries
Intelli J IDEA IDE
SLF4J logging framework
SpringModules Framework for Annotation based data validation

the following diagram shows you the standard directory structure  of this sample web application. (it is importnat to note that you are not required to have DAO, Service and Validation sub packages under the org.conver.registration package for this web application. i composed this post and took this screenshot while i was enhancing this simple tutorial to integrate data access using hibernate and JPA. you will get that example in my future post. :) )




now we can see the content of the each file in detailed as follows.


1. web.xml file


    Spring3-SpringModules-Annotation based Data Validation-Example

    
        index.jsp
    

    
    
        log4jConfigLocation/resources/log4j.xml

    
    
        registration
        
            org.springframework.web.servlet.DispatcherServlet
        
        1
    

    
        registration
        /
    


    
        
            org.springframework.web.context.ContextLoaderListener
        
    




In web, XMl you are required to notedown the following points.

*. log4j.xml file configuration for adding logging framework support(either log4j or slf4j for this project)

*.Spring MVC Front Controller Mapping known as MVC dsipatcher servlet

2. the below JSP page represents the user registration view that is displayed to the user for getting the required user inputs.

userRegisterView.jsp file

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<html>
<head><title><spring:message code="registration.page.name"/></title>
</head>
<body>

<form:form commandName="user" method="POST" action="register">

    <p><spring:message code="registration.form.header"/> </p>
    <form:label path="username"><spring:message code="registration.label.username"/></form:label>
    <form:input path="username"/>
    <form:errors path="username"/>
    <br/>

    <form:label path="password"><spring:message code="registration.label.password"/></form:label>
    <form:password path="password"/>
    <form:errors path="password"/>
    <br/>

    <form:label path="email"><spring:message code="registration.label.email"/></form:label>
    <form:input path="email"/>
    <form:errors path="email"/>
    </br>
    <input type="submit" value="register" />

</form:form>

<spring:message code="registration.page.copyright.information"/>

</body>
</html>

Important things to note
JSTL tag libraries has been used
spring message binding with external property files



once the user press the register button, it will submit the data using POST method to the relevant controller method that is dedicated for the register URL pattern.In addition, it will bind all the user input for the model object provided as the user in the request scope.  you can see the main controller as below.

3. UserAdministration.java file
package org.convey.registration.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.convey.registration.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Map;

/**
 * $LastChangedDate:  $
 * $LastChangedBy:  $
 * $LastChangedRevision:  $
 *
 *  Author: Chathuranga Tennakoon ( chathuranga.t@gmail.com  tel: 009475961039 )
 */
@Controller
@RequestMapping("/userRegistration")
public class UserAdministration {

    final static Logger logger = LoggerFactory.getLogger(UserAdministration.class);

    @Autowired
    private Validator validator;

    @RequestMapping(value="/register", method = RequestMethod.GET)
    public String displayUserRegistrationForm(Map<String, Object> map){

        logger.debug(" request is for displaying the user registration form ");

        //setting up the  required value in the request scope for CommandName parameter
        map.put("user",new User());
        // InternalViewResolver will resolve the logical view name to the actual physical views name
        return "userRegisterView";
    }


    @RequestMapping(value= "/register" , method = RequestMethod.POST)
    public ModelAndView registerNewUser(@ModelAttribute("user")User user, BindingResult result){

        logger.debug(" Form data retrieved from the user registration page and Data validation starts ");

        String password=user.getPassword();
        String username=user.getUsername();
        String email=user.getEmail();

        //here we are using slf4j for logging
        logger.debug(" retrieved username is [{}] ",username);

        ModelAndView view=new ModelAndView("userRegistrationSuccessView");
        // the below parameters can be access in userRegistrationSuccessView jsp page using Expression language (EL)
        view.addObject("password",password);
        view.addObject("username",username);
        view.addObject("email",email);

        validator.validate(user, result);

        logger.debug(" has form errors?  [{}] ",result.hasErrors());

        if (result.hasErrors()) {

            logger.debug(" errors occurred during the validation process ");

            ModelAndView userRegisterFormView=new ModelAndView("userRegisterView");

            return userRegisterFormView;
        }
        else{
            logger.debug(" all data was properly validated with no errors ");
            return view;
        }

    }


} 

the below class is the model class called User. you can see that we have used the validation annotations provided in the springmodules framework for validating the user inputs captured from the user interface given above(userRegisterView.jsp)

4.User.java file (data model class)
package org.convey.registration.model;

import org.springframework.stereotype.Component;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Email;
import org.springmodules.validation.bean.conf.loader.annotation.handler.Length;
import org.springmodules.validation.bean.conf.loader.annotation.handler.NotBlank;

/**
 * $LastChangedDate:  $
 * $LastChangedBy:  $
 * $LastChangedRevision:  $
 *
 * Author: Chathuranga Tennakoon ( chathuranga.t@gmail.com  tel: 009475961039 )
 */
@Component
public class User {

    /* all validation error messages has been defined inside the messages.properties file. */
    @NotBlank
    @Length(min = 5, max = 20)
    private String username;

    @NotBlank
    @Length(min = 5, max = 20)
    private String password;

    @NotBlank
    @Email
    private String email;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

since we have used @Component annotation for the User class (POJO class), it is not required to define the bean in the xml files. since we have declared
    <context:component-scan base-package="org.convey.registration" />
in the xml configuration file, it will automatically discover the classes (that are inside the above package or its sub packages) with the @Component annotations  and initiates their instances in the spring web container at the web application loading time.


you can see that we have used spring modules annotations for the user input validation. all the validations messages have been defined inside the messages.properties file. that can be shown as below.


5. messages.properties file
#User Registration From Page
registration.page.name=User Registration Page
registration.form.header= User Registration Form
registration.label.username=Username
registration.label.password=Password
registration.label.email=Email Address
registration.page.copyright.information=Developed by chathuranga.t@gmail.com (tel 0094759610139)


#User Registration Form Validation messages
User.username[not.blank]=Username is required
User.username[length]=Username length should be minimum {1} to maximum {2} Characters.
User.username[regexp]=Username can contains only lowercase and uppercase characters

User.password[not.blank]=Password is required
User.password[length]=Password length should be minimum {1} to maximum {2} Characters.

User.email[email]=Invalid characters for the email
User.email[not.blank]=Email is required


6. applicationContext.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- the below bean is configured to define external property file for defining property values for the application.
           the following bean is used for configuring a resource bundle for this application based on different locales-->
    <bean id="messageSource"
     class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:properties/messages" />
    <property name="defaultEncoding" value="UTF-8"/>
    </bean>

</beans>

7.registration-servlet.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- this will scan the @Component models defined in the given package (including sub packages) and it will automatically create instances.
         if you have used @Component annotation, it is not required to define the beans  in the XML configuration files -->
    <!-- Discover POJO @Components -->
    <context:component-scan base-package="org.convey.registration" />

    <import resource="applicationContext.xml"/>

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>


    <bean id="handlerMappingC"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property
                name="mappings">
            <props>
                <prop
                        key="/userRegistration/*">
                    userAdministrationController
                </prop>
                <prop
                        key="/userRegistration/register/*">
                    userAdministrationController
                </prop>

            </props>
        </property>
    </bean>


    <bean id="userAdministrationController" class="org.convey.registration.controller.UserAdministration"/>

 <bean id="configurationLoader"
         class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader"/>
 <bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
         p:configurationLoader-ref="configurationLoader"/>

</beans>

8. userRegistrationsuccessView.jsp 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
        <head><title>User Registration success Page.</title></head>
        <body>
               <b>user registration process success</b>

              <h2>username ${username}</h2>
              <h2>password ${password}</h2>
              <h2>email ${email}</h2>
        </body>
</html>


9. pom.xml file




    4.0.0
    SpringHibernate
    hibernate
    war
    1.0
    hibernate

    
        
            JBoss repository
            http://repository.jboss.com/maven2/
        

        
            maven2-repository.dev.java.net
            Java.net Repository for Maven
            http://download.java.net/maven/2/
            default
        

    


    
        UTF-8
        3.0.5.RELEASE
    

    
        

        
            org.springframework
            spring-web
            ${org.springframework.version}
        

        
            org.springframework
            spring-webmvc
            ${org.springframework.version}
        

        

        
            org.slf4j
            slf4j-log4j12
            1.5.6
        

        

        
        
            javax.servlet
            jstl
            1.1.2
        

        
            taglibs
            standard
            1.1.2
        
        

        
        
            org.springmodules
            spring-modules-validation
            0.9
        

        
        
            commons-lang
            commons-lang
            2.3
        

        
            commons-collections
            commons-collections
            3.1
        

    


    
        

            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.6
                    1.6

                

            


            
            

                org.apache.maven.plugins
                maven-war-plugin
                2.0.2

                
                
                    src/main/webapps
                

            

        
        hibernate
    


you can access the project through the following link.


http://localhost:8080/hibername/userRegistration/register



you can download the full source code  for the project through the following link.

Download Source


In addition, the source code is available at the following GIT repository.

git@github.com:chathurangat/SpringModules-Annotation-based-Validation.git
 

once the source is downloaded, you will have to execute the  following command in the vi editor for building the project using maven.

maven clean install -DskipTests

once the project is build, copy the hibernate.war file (that is inside the target directory) to the webapps directory of your tomcat server.

regards
Chathuranga Tennakoon
chathuranga.t@gmail.com

No comments:

Post a Comment