Search code examples
javaspringspring-mvclocalizationspring-validator

Spring validator error code is not auto resolve


Message source config:

@Bean
public MessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames("classpath:locale/normal/message", "classpath:locale/validation/message");
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
}

Spring validator:

@Component
public class MyAccountValidator implements Validator {

    @Autowired
    MyAccountService myAccountService;

    @Override
    public boolean supports(Class<?> clazz) {       
        return MyAccount.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {

        MyAccount myAccount = (MyAccount) target;

        MyAccount myAccountDb = myAccountService.findByUserId(myAccount.getUserId());

        if (myAccountDb == null) {
            errors.reject("myAccount.id.not_found");
        }
    }
}

message_en.properties:

myAccount.id.not_found=Your id is not found.

hibernate validator:

@NotNull(message="{myAccount.id.not_found}")
private String password;

Spring controller:

@RequestMapping(value = { "/validate" }, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String validate(Model model, @RequestBody @Valid MyAccount myAccount, BindingResult bindingResult, Locale locale) throws JsonProcessingException {

    System.out.println("myAccount user id = " + myAccount.getUserId());

    String msg = "";
    List<ObjectError> errors = bindingResult.getAllErrors();
    for (ObjectError error : errors ) {
        msg = msg + (error.getObjectName() + " - " + error.getCode() + " - " + error.getDefaultMessage()) + "\n";
    }                       

    return msg;
}

In my controller, error.getDefaultMessage() is always showing null value for the Spring validator error code errors.reject("myAccount.id.not_found");, it cannot be resolved automatically.

When I try hibernate validator as you can see in the field annotation above, it is working fine, @NotNull(message="{myAccount.id.not_found}") can be resolved perfectly in each of the locale automatically.

Do I miss out any configuration? Why the Spring validator error code not working automatically?

PS: My I18N configuration should be correct, all my JSP can display the text correctly.


Solution

  • I have been searching for whole day, probably there is no answer for my question... I conclude some of my findings:

    1) Reading through lot of tutorials, all of them display the error message in JSP view, so they could probably get it work like this: <form:errors path="*" cssClass="error" element="div"/>, error code will got resolved to locale message automatically. But in my case, I want to get the error message via ajax, so, to resolve the error code in controller, I have to do it manually, unfortunately I have to inject messagesource and locale in my controller:

    @RequestMapping(value = { "/validate" }, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_HTML_VALUE)
    @ResponseBody
    public String validate(Model model, @RequestBody @Valid MyAccount myAccount, BindingResult bindingResult, Locale locale) throws JsonProcessingException {
    
        System.out.println("myAccount user id = " + myAccount.getUserId());
    
        String msg = "";
        List<ObjectError> errors = bindingResult.getAllErrors();
        for (ObjectError error : errors ) {
            msg = msg + (messageSource.getMessage(error, locale)) + "\n";
        }                       
    
        return msg;
    }
    

    2) Have a read on the Resolving codes to error messages, the resolver is to resolve the error code to one or multiple message code, it doesn't help to map the message code to the message values in the messagesource. I have misunderstand the term between error code and message code.

    If someone who has the solution, please share...