Spring MVC form validation with Java Validation API
Tools and Technologies used
1)Eclipse IDE Mars Release (4.5.0)
2)Java 8
3)Spring framework 4.2
4)Tomcat 8
5)Validation API
In spring MVC , we can validate the form in many ways , we can use validation API ,custom validator or directly validating in controller after the form submit.
Lets see how we can do the same using Java Validation API.
Java Validation API suggests us to use annotation on the model class for each attribute to specify the validation constraints.
Example:
- public class Customer {
- @NotNull
- @Email
- private String emailId;
- @NotNull
- @Size(min=8,max=15)
- private String password;
- //getters and setters
- }
public class Customer { @NotNull @Email private String emailId; @NotNull @Size(min=8,max=15) private String password; //getters and setters }
So we are using @NotNull to specify that emailId and password fields should not be null.
@Email – specifies that , emailId field is getting validated as per the email standard provided by Hibernate validator.
@Size specifies that password field should be minimum of 8 characters and maximum of 15 characters.
We can use many other annotations to validate the fields in the form.
In the controller class, specify the form backing model object with @Valid annotation to ensure that form values gets binded with this model object and do the validation.
- @Controller
- public class LoginController {
- @RequestMapping(value = "/doLogin", method = RequestMethod.POST)
- public String doLogin(@Valid User user, BindingResult result) {
- // login logic here
- }
- }
@Controller public class LoginController { @RequestMapping(value = "/doLogin", method = RequestMethod.POST) public String doLogin(@Valid User user, BindingResult result) { // login logic here } }
If any validation error occurs as per our validation defined in the model class, then BindingResult will have the errors.
- if (result.hasErrors()) {
- // form validation error, return the same form
- } else {
- // form input is fine, continue the flow
- }
if (result.hasErrors()) { // form validation error, return the same form } else { // form input is fine, continue the flow }
so we can check the binding results for any errors.
If it has errors we can return the same form with error message, if not we can continue the flow.
We can display the error messages on the jsp by using spring’s form errors tag as follows
- <form:errors path="emailId" />
<form:errors path="emailId" />
Where emailId is the exact attribute name in the Customer Model class.
We can also specify the error message while specifying the validation constraints in the model class with annotation as below
- @NotEmpty(message = "Email Id is Required.")
- private String emailId;
@NotEmpty(message = "Email Id is Required.") private String emailId;
since error message has to be localized, we will specify it in the properties file.
The way of specifying the key in the properties file is
- ConstraintName.modelAttributeName.propertyName=validation error message
ConstraintName.modelAttributeName.propertyName=validation error message
Example
- NotEmpty.customer.emailId=Email Id is Required.
NotEmpty.customer.emailId=Email Id is Required.
Lets see full example
Project structure is as below
Create the Model class as below
- package com.kb.model;
- import javax.validation.constraints.NotNull;
- import javax.validation.constraints.Size;
- import org.hibernate.validator.constraints.Email;
- import org.hibernate.validator.constraints.NotEmpty;
- public class Customer {
- @NotNull
- @NotEmpty
- @Email
- private String emailId;
- @NotNull
- @Size(min=8,max=15)
- private String password;
- public String getEmailId() {
- return emailId;
- }
- public void setEmailId(String emailId) {
- this.emailId = emailId;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
package com.kb.model; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; public class Customer { @NotNull @NotEmpty @Email private String emailId; @NotNull @Size(min=8,max=15) private String password; public String getEmailId() { return emailId; } public void setEmailId(String emailId) { this.emailId = emailId; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
Create the login jsp page as below
- <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
- <html>
- <head>
- <title>Spring MVC form Validation</title>
- </head>
- <body>
- <h2>Enter below details to login</h2>
- <form:form method="POST" modelAttribute="customer" action="doLogin">
- <table>
- <tr>
- <td>Enter your E-mail:</td>
- <td><form:input path="emailId" /></td>
- <td><form:errors path="emailId" cssStyle="color: #ff0000;" /></td>
- </tr>
- <tr>
- <td>Enter a password:</td>
- <td><form:password path="password" showPassword="true"/></td>
- <td><form:errors path="password" cssStyle="color: #ff0000;"/></td>
- </tr>
- <tr>
- <td><input type="submit" name="submit" value="Register"></td>
- </tr>
- </table>
- </form:form>
- </body>
- </html>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <html> <head> <title>Spring MVC form Validation</title> </head> <body> <h2>Enter below details to login</h2> <form:form method="POST" modelAttribute="customer" action="doLogin"> <table> <tr> <td>Enter your E-mail:</td> <td><form:input path="emailId" /></td> <td><form:errors path="emailId" cssStyle="color: #ff0000;" /></td> </tr> <tr> <td>Enter a password:</td> <td><form:password path="password" showPassword="true"/></td> <td><form:errors path="password" cssStyle="color: #ff0000;"/></td> </tr> <tr> <td><input type="submit" name="submit" value="Register"></td> </tr> </table> </form:form> </body> </html>
Create the login home jsp page as below
- <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="ISO-8859-1"%>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Insert title here</title>
- </head>
- <body>
- <div align="center">
- <h2>Welcome ${customer.emailId}! You have logged in successfully.</h2>
- </div>
- </body>
- </html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <div align="center"> <h2>Welcome ${customer.emailId}! You have logged in successfully.</h2> </div> </body> </html>
Create the controller class as below
- package com.kb.controller;
- import javax.validation.Valid;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.validation.BindingResult;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import com.kb.model.Customer;
- @Controller
- public class LoginController {
- @RequestMapping(value = "/login", method = RequestMethod.GET)
- public String viewLoginPage(Model model) {
- Customer customer = new Customer();
- model.addAttribute("customer", customer);
- return "login";
- }
- @RequestMapping(value = "/doLogin", method = RequestMethod.POST)
- public String doLogin(@Valid Customer customer, BindingResult result,Model model) {
- model.addAttribute("customer",customer);
- if(result.hasErrors()){
- return "login";
- }
- return "home";
- }
- }
package com.kb.controller; import javax.validation.Valid; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.kb.model.Customer; @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String viewLoginPage(Model model) { Customer customer = new Customer(); model.addAttribute("customer", customer); return "login"; } @RequestMapping(value = "/doLogin", method = RequestMethod.POST) public String doLogin(@Valid Customer customer, BindingResult result,Model model) { model.addAttribute("customer",customer); if(result.hasErrors()){ return "login"; } return "home"; } }
Create the spring mvc configuraton 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"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
- <context:component-scan base-package="com.kb.*" />
- <mvc:annotation-driven />
- <bean id="viewResolver"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/pages/" />
- <property name="suffix" value=".jsp" />
- </bean>
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="/WEB-INF/messages" />
- </bean>
- </beans>
<?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" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.kb.*" /> <mvc:annotation-driven /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/" /> <property name="suffix" value=".jsp" /> </bean> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="/WEB-INF/messages" /> </bean> </beans>
Create the web.xml as below
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
- <display-name>Spring MVC Form Validation-Bean-API</display-name>
- <!-- Spring MVC dispatcher servlet -->
- <servlet>
- <servlet-name>mvc-dispatcher</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring-mvc.xml,
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>mvc-dispatcher</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- Loads Spring Security configuration file -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/spring-mvc.xml,
- </param-value>
- </context-param>
- </web-app>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Spring MVC Form Validation-Bean-API</display-name> <!-- Spring MVC dispatcher servlet --> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-mvc.xml, </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Loads Spring Security configuration file --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-mvc.xml, </param-value> </context-param> </web-app>
Create the pom.xml as below
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>Spring</groupId>
- <artifactId>Spring-form-validation</artifactId>
- <packaging>war</packaging>
- <version>0.0.1-SNAPSHOT</version>
- <name>Spring-form-validation Maven Webapp</name>
- <url>http://maven.apache.org</url>
- <properties>
- <org.springframework.version>4.2.0.RELEASE</org.springframework.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>${org.springframework.version}</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet.jsp.jstl</groupId>
- <artifactId>javax.servlet.jsp.jstl-api</artifactId>
- <version>1.2.1</version>
- </dependency>
- <dependency>
- <groupId>taglibs</groupId>
- <artifactId>standard</artifactId>
- <version>1.1.2</version>
- </dependency>
- <dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>1.1.0.Final</version>
- </dependency>
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>5.0.1.Final</version>
- </dependency>
- </dependencies>
- <build>
- <finalName>SpringMVCFormValidationBeanValidator</finalName>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.5.1</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Spring</groupId> <artifactId>Spring-form-validation</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Spring-form-validation Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <org.springframework.version>4.2.0.RELEASE</org.springframework.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.0.1.Final</version> </dependency> </dependencies> <build> <finalName>SpringMVCFormValidationBeanValidator</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
Create the messages.properties file as below inside WEB-INF folder
- NotEmpty.customer.emailId=Email Id is required.
- Email.customer.emailId=valid email id is required.
- NotEmpty.customer.password=Password is required.
- Size.customer.password=Password should be minimum of 8 and maximum of 15 characters.
NotEmpty.customer.emailId=Email Id is required. Email.customer.emailId=valid email id is required. NotEmpty.customer.password=Password is required. Size.customer.password=Password should be minimum of 8 and maximum of 15 characters.
Build the project and copy the war file into webapps folder of Tomcat and start the server.
Access the below url
http://localhost:8080/SpringMVCFormValidationBeanValidator/login
Don’t enter anything, just click on Login button to see the validation
Since we have written @NotEmpty annotation on each field, valdator throws error if the fields are empty.
Enter Invalid Email format as below and see @Email throws validation error
Since we have used resource bundle message source for localization, all Customized error messages are coming from messages.properties file. Otherwise we will see default error messages.
Now enter valid email and password and click on Login
And see the below home page
nICE
Thanks, Good Article.It helped me.