4

I have an Object called officers i would like to preform different types of validation based on the function the user wants to preform, for e.g when a officer record is being registered/saved i would like to preform a check if its NULL and generate a officer number and when a record is being updated i would not like to not preform this check and execute an update statement.

However i am having problems achieving this since. I have looked at different approaches and it isnt clean enough or flexible. I have tried the following approaches and the problems faced are;

  1. Using a Registered Validator with the Controller however each Controller only allows one Validator to be registered. This makes the implementation of that validation apply to all functions preformed in the controller.

    1. Using a Validator Facade could allow one validation class for the entire application however it selects validation based on instance type for objects and this limits the number of validators per object to one(stand to be corrected).

How is it possible to preform different validation for the same object without using a separate Controller for the method.

Class Officers

   public class Officers implements Serializable{


        private String userName;
        private String password;
        private String password2;
        private String fName;
        private String lName;
        private String oName;
        private int divisionNo;
        private officerNumber;

OfficerRegistrationValidation Class

    @Component
    public class OfficerRegistrationValidation implements Validator {

        public boolean supports(Class<?> clazz) {

            return Officers.class.equals(clazz);
        }

        public void validate(Object target, Errors errors) {

            Officers officer = (Officers) target;

    if (officer.getPassword() == null) {
                errors.rejectValue("password", "password.required");
            }

            if (officer.getPassword2() == null) {
                errors.rejectValue("password2", "password2.required");
            }
..............
}

Controller

@Controller
public class OfficerController {


    @InitBinder("officers")
    protected void initBinder(WebDataBinder binder){


        //removes white spaces 
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));

        //formats date 
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        //By passing true this will convert empty strings to null
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        dateFormat.setLenient(false);


        //binder.setValidator(new OfficerRegistrationValidation());
        binder.setValidator(officerRegistrationValidation);



    }

 @RequestMapping(value="officer_registration_save.htm", method = RequestMethod.POST)
public ModelAndView loadPage(HttpServletRequest request,HttpServletResponse response,
@ModelAttribute Officers officer,BindingResult result,ModelMap m, Model model) throws Exception {    

    if(result.hasErrors()){

          return new ModelAndView("officer_registration");

     }else 

          doSave();

}

Need to use a different type of validation for a record to be updated

 @RequestMapping(value="officer_registration_update.htm", method = RequestMethod.POST)
public ModelAndView loadPage(HttpServletRequest request,HttpServletResponse response,
@ModelAttribute Officers officer,BindingResult result,ModelMap m, Model model) throws Exception {    

    if(result.hasErrors()){

          return new ModelAndView("officer_registration");

     }else 

          doSave();

}

The approach i end up using was getting the button value either update or save via HttpServletRequest and including that in the validator to decide whether to validate for an update or a save. Has anyone done anything similar before i am looking for he cleanest and best approach. So far i have decided to use HttpServletRequest request request.getParameter("action"); I find this approach to be a little old and not clean.

1
  • 2
    I don't think that using multiple validators for the same class is the right thing to do. Validation for an object should be the same regardless of the operation being performed. The scenario for generating a new customer number, should be better handled by the save method in your service layer probably. Commented May 22, 2013 at 3:59

1 Answer 1

7

You don't need to register your validators in the WebDataBinder. Instead, you can create two (or any number) different Validator classes for each of your requirements. For example

public class OfficerRegistrationValidation implements Validator {...}

public class OfficerUpdateValidation implements Validator {...}

Create beans for each of these, either with @Component or a <bean> declaration. Inject them in your @Controller class

@Controller
public class OfficerController {
    @Inject
    private OfficerRegistrationValidation officerRegistrationValidation;

    @Inject
    private OfficerUpdateValidation officerUpdateValidation;

Then use the specific one you need in each of your methods

@RequestMapping(method = RequestMethod.POST) 
public /* or other return type */ String registerOfficer(@Valid @ModelAttribute Officer officer, BindingResult errors /*, more parameters */) {
    officerRegistrationValidation.validate(officer, errors);
    if (errors.hasErrors()) {
        ...// do something
    }
    ...// return something
}

Don't register either of these in the WebDataBinder. @Valid will perform default validation, for example, for @NotEmpty or @Pattern annotations. Your Validator instances will perform custom validation for the specific use case.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.