Saturday, April 18, 2020

Spring MVC Custom Validator Example

In spring mvc form submit tutorial, we learned about displaying displaying a form and submitting form data, including validating inputs using BindingResult.rejectValue(). In this example, we will learn to build a more robust validator for EmployeeVO model object. This validator is custom implementation of Validator interface. In this example, I am modifying the code used for form submit example we built in last tutorial.

Custom Validator Implementation

Spring MVC supports validation by means of a validator object that implements the Validator interface. You can write the following validator to check if the required form fields are filled.
package com.howtodoinjava.demo.validator;
 
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
 
import com.howtodoinjava.demo.model.EmployeeVO;
 
@Component
public class EmployeeValidator implements Validator
{
 
    public boolean supports(Class clazz) {
        return EmployeeVO.class.isAssignableFrom(clazz);
    }
 
    public void validate(Object target, Errors errors)
    {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "error.firstName", "First name is required.");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "error.lastName", "Last name is required.");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "error.email", "Email is required.");
    }
 
}
In this validator, you use utility methods such as rejectIfEmptyOrWhitespace() and rejectIfEmpty() in the ValidationUtils class to validate the required form fields. If any of these form fields is empty, these methods will create a field error and bind it to the field. The second argument of these methods is the property name, while the third and fourth are the error code and default error message.
Many times validation errors are not specific to fields. For example end date should be greater than start date. In this case, you can use the reject() method to create an object error to be bound to the EmployeeVO object, not to a field.
e.g. errors.reject(“invalid.dateDiff”, “End date should be greater than start date.”);
To activate this custom validator as a spring managed bean, you need to do one of following things:
1) Add @Component annotation to EmployeeValidator class and activate annotation scanning on the package containing such declarations.
<context:component-scan base-package="com.howtodoinjava.demo" />
2) Alternatively, you can register the validator class bean directly in context file.
<bean id="employeeValidator" class="com.howtodoinjava.demo.validator.EmployeeValidator" />

Controller Changes

To apply this validator, you need to perform the following modification to your controller.
1) Include validator reference to controller class and mark it autowired to ensure it’s available when needed.
@Autowired
EmployeeValidator validator;
2) Next change is in controller’s post method which is called when user submit the form.
@RequestMapping(method = RequestMethod.POST)
public String submitForm(@ModelAttribute("employee") EmployeeVO employeeVO,
                        BindingResult result, SessionStatus status)
{
     
    //Validation code
    validator.validate(employeeVO, result);
     
    //Check validation errors
    if (result.hasErrors()) {
        return "addEmployee";
    }
     
    //Store the employee information in database
    //manager.createNewRecord(employeeVO);
     
    //Mark Session Complete
    status.setComplete();
    return "redirect:addNew/success";
}
Once the validate method returns, the result parameter i.e. BindingResult contains the results for the validation process. You can check if there was any error in input using result.hasErrors() method call. If any error is detected you can again render the form view to let user correct it’s input.
If there is no error found then result.hasErrors() will return false, then you can simply process the input and redirect the user to next view.
Complete sourcecode foe controller used in this example is below:
package com.howtodoinjava.demo.controller;
 
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.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.model.EmployeeVO;
import com.howtodoinjava.demo.service.EmployeeManager;
import com.howtodoinjava.demo.validator.EmployeeValidator;
 
@Controller
@RequestMapping("/employee-module/addNew")
@SessionAttributes("employee")
public class EmployeeController
{
    @Autowired
    EmployeeManager manager;
     
    @Autowired
    EmployeeValidator validator;
     
    @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)
    {
         
        validator.validate(employeeVO, result);
         
        if (result.hasErrors()) {
            return "addEmployee";
        }
        //Store the employee information in database
        //manager.createNewRecord(employeeVO);
         
        //Mark Session Complete
        status.setComplete();
        return "redirect:addNew/success";
    }
     
    @RequestMapping(value = "/success", method = RequestMethod.GET)
    public String success(Model model)
    {
         return "addSuccess";
    }
}

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...