Saturday, April 18, 2020

Spring MVC Populate and Validate Dropdown Example

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.
Spring MVC Dropdown Example - Blank Form
Spring MVC Dropdown Example – Blank 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 departmentDepartmentEditor 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
Spring MVC Dropdown Example - Blank Form
Spring MVC Dropdown Example – Blank Form
2) Fill first name and Submit the form. You will validation message.
Spring MVC Dropdown Example - Dropdown ValidationSpring MVC Dropdown Example - Dropdown Validation
Spring MVC Dropdown Example – Dropdown Validation
3) Select a department from list and submit the form. You will success page.
Spring MVC Form Example - Success Message
Spring MVC Form Example – Success Message

No comments:

Post a Comment

How to DROP SEQUENCE in Oracle?

  Oracle  DROP SEQUENCE   overview The  DROP SEQUENCE  the statement allows you to remove a sequence from the database. Here is the basic sy...