If you are working on any customer facing web application which is developed using Spring MVC, then your will probably need to use dropdown box as well somewhere in application UI. This tutorial will help you in displaying a pre-populated dropdown and then validating whether user selected any value while submitting the form or not.
This post is in continuation to my previous post about spring mvc validation using JSR-303 annotations. I will be modifying the same sourcecode.
In this example, I will display a form for adding new Employee into system. This form will have a dropdown listing all departments. Application user must select one a value from dropdown before submitting the form.
Table of Contents
Model Classes
Adding PropertyEditorSupport
View layer changes for displaying Dropdown box
Dropdown validation changes
Test The Application
Model Classes
DepartmentVO.java
package com.howtodoinjava.demo.model; public class DepartmentVO { public DepartmentVO(Integer id, String name) { super (); this .id = id; this .name = name; } private Integer id; private String name; //Setters and Getters @Override public String toString() { return "DepartmentVO [id=" + id + ", name=" + name + "]" ; } } |
EmployeeVO.java
This class has associated attribute for
DepartmentVO
.package com.howtodoinjava.demo.model; import java.io.Serializable; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.NotEmpty; public class EmployeeVO implements Serializable { private static final long serialVersionUID = 1L; private Integer id; @NotEmpty private String firstName; private String lastName; private String email; @NotNull private DepartmentVO department; //Setters and Getters @Override public String toString() { return "EmployeeVO [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", department=" + department + "]" ; } } |
Adding PropertyEditorSupport
we will not show
DepartmentVO
as java object in UI, rather when user submit a property bound to department field, only a string value will come in HTTP POST. We need to have some mechanism to convert that string value back to DepartmentVO
instance and inject into EmployeeVO
instance.
Spring provides
PropertyEditorSupport
classes for this purpose.
DepartmentEditor.java
package com.howtodoinjava.demo.convertor; import java.beans.PropertyEditorSupport; import com.howtodoinjava.demo.model.DepartmentVO; public class DepartmentEditor extends PropertyEditorSupport { //This will be called when user HTTP Post to server a field bound to DepartmentVO @Override public void setAsText(String id) { DepartmentVO d; switch (Integer.parseInt(id)) { case 1 : d = new DepartmentVO( 1 , "Human Resource" ); break ; case 2 : d = new DepartmentVO( 2 , "Finance" ); break ; case 3 : d = new DepartmentVO( 3 , "Information Technology" ); break ; default : d = null ; } this .setValue(d); } } |
This is OK but how spring will know that we have this class for conversion purpose. For that we have to tell spring about it. We can do it in Controller class in below way.
@InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(DepartmentVO. class , new DepartmentEditor()); } |
Now everytime a form is submitted to
EmployeeController
having a field bounded to department
, DepartmentEditor
will be used to convert from string value to DepartmentVO
instance.
The complete code of
EmployeeController
is below.
EmployeeController.java
package com.howtodoinjava.demo.controller; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; 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.bind.annotation.SessionAttributes; import org.springframework.web.bind.support.SessionStatus; import com.howtodoinjava.demo.convertor.DepartmentEditor; import com.howtodoinjava.demo.model.DepartmentVO; import com.howtodoinjava.demo.model.EmployeeVO; import com.howtodoinjava.demo.service.EmployeeManager; @Controller @RequestMapping ( "/employee-module/addNew" ) @SessionAttributes ( "employee" ) public class EmployeeController { @Autowired EmployeeManager manager; private Validator validator; public EmployeeController() { ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); validator = validatorFactory.getValidator(); } @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(DepartmentVO. class , new DepartmentEditor()); } @ModelAttribute ( "allDepartments" ) public List<DepartmentVO> populateDepartments() { ArrayList<DepartmentVO> departments = new ArrayList<DepartmentVO>(); departments.add( new DepartmentVO(- 1 , "Select Department" )); departments.add( new DepartmentVO( 1 , "Human Resource" )); departments.add( new DepartmentVO( 2 , "Finance" )); departments.add( new DepartmentVO( 3 , "Information Technology" )); return departments; } @RequestMapping (method = RequestMethod.GET) public String setupForm(Model model) { EmployeeVO employeeVO = new EmployeeVO(); model.addAttribute( "employee" , employeeVO); return "addEmployee" ; } @RequestMapping (method = RequestMethod.POST) public String submitForm( @ModelAttribute ( "employee" ) EmployeeVO employeeVO, BindingResult result, SessionStatus status) { Set<ConstraintViolation<EmployeeVO>> violations = validator.validate(employeeVO); for (ConstraintViolation<EmployeeVO> violation : violations) { String propertyPath = violation.getPropertyPath().toString(); String message = violation.getMessage(); // Add JSR-303 errors to BindingResult // This allows Spring to display them in view via a FieldError result.addError( new FieldError( "employee" , propertyPath, "Invalid " + propertyPath + "(" + message + ")" )); } if (result.hasErrors()) { return "addEmployee" ; } // Store the employee information in database // manager.createNewRecord(employeeVO); System.out.println(employeeVO); // Mark Session Complete status.setComplete(); return "redirect:addNew/success" ; } @RequestMapping (value = "/success" , method = RequestMethod.GET) public String success(Model model) { return "addSuccess" ; } } |
To Read more about extra pieces of code in this controller, refer to this spring mvc display form tutorial.
View changes for displaying Dropdown box
To display dropdown, you must feed a collection of departments to jsp file. This is done from controller. Please note that in this example I have hardcoded the collection. In production class application, you will need to build this collection dynamically.
@ModelAttribute ( "allDepartments" ) public List<DepartmentVO> populateDepartments() { ArrayList<DepartmentVO> departments = new ArrayList<DepartmentVO>(); departments.add( new DepartmentVO(- 1 , "Select Department" )); departments.add( new DepartmentVO( 1 , "Human Resource" )); departments.add( new DepartmentVO( 2 , "Finance" )); departments.add( new DepartmentVO( 3 , "Information Technology" )); return departments; } |
This
allDepartments
attribute can be accessed inside JSP file in form:select
tag.<%@ page contentType= "text/html;charset=UTF-8" %> <%@ taglib prefix= "form" uri= "http://www.springframework.org/tags/form" %> <%@ taglib prefix= "spring" uri= "http://www.springframework.org/tags" %> <html> <head> <title>Add Employee Form</title> <style> .error { color: #ff0000; font-weight: bold; } </style> </head> <body> <h2><spring:message code= "lbl.page" text= "Add New Employee" /></h2> <br/> <form:form method= "post" modelAttribute= "employee" > <%-- <form:errors path= "*" cssClass= "error" /> --%> <table> <tr> <td><spring:message code= "lbl.firstName" text= "First Name" /></td> <td><form:input path= "firstName" /></td> <td><form:errors path= "firstName" cssClass= "error" /></td> </tr> <tr> <td><spring:message code= "lbl.lastName" text= "Last Name" /></td> <td><form:input path= "lastName" /></td> <td><form:errors path= "lastName" cssClass= "error" /></td> </tr> <tr> <td><spring:message code= "lbl.email" text= "Email Id" /></td> <td><form:input path= "email" /></td> <td><form:errors path= "email" cssClass= "error" /></td> </tr> <!-- DROPDOWN code --> <tr> <td><spring:message code= "lbl.department" text= "Department" /></td> <td><form:select path= "department" items= "${allDepartments}" itemValue= "id" itemLabel= "name" /></td> <td><form:errors path= "department" cssClass= "error" /></td> </tr> <tr> <td colspan= "3" ><input type= "submit" value= "Add Employee" /></td> </tr> </table> </form:form> </body> </html> |
Dropdown Validation
To validate dropdown box, we have used following things.
1) We have used
@NotNull
annotation on department field inside EmployeeVO
. If field is null, spring validation using JSR-303 will automatically raise an error.@NotNull private DepartmentVO department; |
2) As we have
@NotNull
annotation, then all we have to do is to set null in department
field for all unexpected values. This is done inside DepartmentEditor
, because before coming to controller code, DepartmentEditor.setAsText()
is called to set the correct value of department.public void setAsText(String id) { DepartmentVO d; switch (Integer.parseInt(id)) { case 1 : d = new DepartmentVO( 1 , "Human Resource" ); break ; case 2 : d = new DepartmentVO( 2 , "Finance" ); break ; case 3 : d = new DepartmentVO( 3 , "Information Technology" ); break ; default : d = null ; } this .setValue(d); } |
In above code, only if dropdown selected value is either 1,2 or 3; then only a valid instance of department will be set. Otherwise department will be set to null. This null will raise the error.
Test the Dropdown
1) Deploy the application and Enter URL : http://localhost:8080/springmvcexample/employee-module/addNew
2) Fill first name and Submit the form. You will validation message.
3) Select a department from list and submit the form. You will success page.
No comments:
Post a Comment