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;
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With