Spring MVC : Form Handling and Validations

In the previous post we have seen basic flow in spring mvc. Lets build a simple registration form using previous project.

Creating out form – RegistrationForm.java


package mynotes.springmvc.form;

public class RegistrationForm {

private String fname;
private String lname;
private String email;

@Override
public String toString() {
return "fname="+this.fname+"\t"+
"lname="+this.lname+"\t"+
"email="+this.email;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}

}

Creating a jsp that wil display registration form – registration.jsp


<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration</title>
</head>
<body>
<form:form method="post" action="register" commandName="refistrationForm">
<h2><spring:message code="registration.heading"/></h2>
<table>
<tr>
<td><form:label path="fname"><spring:message code="label.fname"/></form:label></td>
<td><form:input path="fname" /></td>
</tr>
<tr>
<td><form:label path="lname"><spring:message code="label.lname"/></form:label></td>
<td><form:input path="lname" /></td>
</tr>
<tr>
<td><form:label path="email"><spring:message code="label.email"/></form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td>
<input type="submit" value="Cancel" formaction="cancelRegistration" formmethod="get"/>
</td>
<td>
<input type="submit" value="Register"/>
</td>
</tr>
</table>

</form:form>
</body>
</html>

Notice above the default action in form:form is mapped to action=”register”. We have to make this mapping in our controller. Also there is an attribute commandName=”refistrationForm”commandName is the name of the model attribute under which the form object is exposed (done in controller). Defaults value is ‘command’. The exact same thing can be said of ‘modelAttribute’. You got to have one mentioned if you have a name other than the default (command). Also it needs to be setted in controller. Also notice the formaction=”cancelRegistration” in Cancel button. This is another mapping that needs to be created in our controller. The form:input, form:label path attribute should be of same name as that of your form member variables of RegistrationForm class. spring:message code is coming from properties file which is already loaded by your dispatcher.

Creating a success page – registration_success.jsp


<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Success</title>
</head>
<body>
<form>
<table>
<tr><td><spring:message code="registration.success"/></td></tr>
</table>
</form>
</body>
</html>

Changing the registration_intro.jsp slightly :


<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Intro</title>
</head>
<body>
<form>
<table>
<tr><td colspan="2"><spring:message code="registration.intro1"/></td></tr>
<tr><td><spring:message code="registration.intro2"/></td>
<td><a href="/MyNotes_Spring_MVC/intializeRegistration">Register</a> </td></tr>
</table>
</form>
</body>
</html>

Notice the intializeRegistration href, another mapping to be created in controller.

Adding above mentioned mappings to our Controller – RegistrationController.java


package mynotes.springmvc.controller;

import mynotes.springmvc.form.RegistrationForm;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class RegistrationController {

@RequestMapping(value = "/registrationIntro", method = RequestMethod.GET)
public String registrationIntro() {

System.out.println("Inside registrationIntro");

return "registration_intro";
}

@RequestMapping(value = "/intializeRegistration", method = RequestMethod.GET)
public ModelAndView initializeRegistration() {

System.out.println("Inside initializeRegistration");
ModelAndView mav=new ModelAndView();
mav.addObject("refistrationForm", new RegistrationForm());
mav.setViewName("registration");

return mav;
}

@RequestMapping(value = "/cancelRegistration", method = RequestMethod.GET)
public ModelAndView cancelRegistration() {

System.out.println("Inside cancelRegistration");
ModelAndView mav=new ModelAndView();
mav.setViewName("registration_intro");

return mav;
}

@RequestMapping(value = "/register", method = RequestMethod.POST)
public ModelAndView register(
@ModelAttribute("refistrationForm") RegistrationForm registrationForm) {

System.out.println("Inside register");
System.out.println("registrationForm==>" + registrationForm);

ModelAndView mav=new ModelAndView();
mav.addObject("refistrationForm", new RegistrationForm());
mav.setViewName("registration_success");

return mav;
}

}

We have added the requred Request mapping. Notice in initializeRegistration() we are using ModelAndView as return object. ModelAndView exposes several methods to add attributes for use in the view. The constructor is also capable of accepting attribute as name value pairs. However for clarity we are addind objects. In initializeRegistration(), we added ‘refistrationForm’ to ModelAndView with RegistrationForm. This should be of same name as the value in commandName in jsp. Then we setted the view to ‘registration’.
The register() has a parameter @ModelAttribute to the whole form as an input so we do not have to do request.get many times. Rest all are self explanatory.

ApplicationResource.properties


registration.intro1=Welcome to Spring MVC Registration Demo
registration.intro2=Click 'Register' button to start

registration.heading=Registration Form
registration.success= Your registration has been successfully completed.

label.fname=First Name :
label.lname=Last Name :
label.email=Email :

error.reqired=Required Filed
invalid.email=Invalid Email

Running on server:

Springmvc_registrationResultView11 Springmvc_registrationResultView12 Springmvc_registrationResultView13

Lets implement a validator to check all the form values. RegistrationValidator.java


package mynotes.springmvc.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import mynotes.springmvc.form.RegistrationForm;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@Component
public class RegistrationValidator implements Validator {

public boolean supports(Class<?> clazz) {

return clazz.isAssignableFrom(RegistrationForm.class);
}

public void validate(Object obj, Errors errors) {

RegistrationForm registrationForm = (RegistrationForm) obj;

ValidationUtils.rejectIfEmptyOrWhitespace(errors, "fname","error.reqired");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lname","error.reqired");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email","error.reqired");

if (registrationForm.getEmail() != null) {
String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
Pattern pattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = pattern.matcher(registrationForm.getEmail());
if (!matcher.matches()) {
errors.rejectValue("email", "invalid.email");
}
}

}

}

As you can see we have created a class RegistrationValidator  which implements Validator interface of spring. We have to override 2 methods. In supports() method we have to tell which Form classes are suported by this validator. For us its RegistrationForm. The validate() methods validate member variables of the Form class. There are few overloaded methods, you check the docs for all. The 3rd parameter in rejectIfEmptyOrWhitespace() method is the property file key, that needs to be shown to the user. The second parameter is the member variable of the class that needs to be validated. A custom validation of email has also been done. Also notice that we have declared this class as @Component i.e spring will create a bean of it.

Addind this validator in our RegistrationController.java:


@Controller
public class RegistrationController {

@Autowired
private RegistrationValidator registrationValidator;

//rest all remains same as previous

@RequestMapping(value = "/register", method = RequestMethod.POST)
public ModelAndView register(
@ModelAttribute("refistrationForm") RegistrationForm registrationForm,
BindingResult results) {

System.out.println("Inside register");
System.out.println("registrationForm==>" + registrationForm);
ModelAndView mav = new ModelAndView();
mav.addObject("refistrationForm", new RegistrationForm());
registrationValidator.validate(registrationForm, results);

if (results.hasErrors()) {
mav.setViewName("registration");
} else {
mav.setViewName("registration_success");
}

return mav;
}

We have autowired the validator bean. The register() method has BindingResult as a parameter. To validate registrationForm, just call .validate() passing RegistrationForm and BindingResult . If the results has errors set view to the same page else move to success page.

Springmvc_registrationResultView_validatorError

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: