A good practice to present service level validation errors to the user using Spring MVC
java, spring, spring-mvc, validation
Solution
The choice is typically exceptions vs. error codes (or response codes), but the best practice, at least Bloch's, is to only use exceptions in exceptional circumstances, which disqualifies them in this situation, since a user picking an existing username isn't unheard of.
The issue in your service call is that you assume `createUser` is an imperative command with no return value. You should think of it as "try to create a user, and give me a result" instead. That result could then be
- an integer code (horrible idea)
- a constant from a shared Result enum (still a bad idea due to maintainability)
- a constant from something more specific like a `UserOperationResult` enum (better idea since you might want to return `USER_ALREADY_EXISTS` both when you create a new user and when you try to modify a user)
- a `UserCreationResult` object that's completely custom to this call (not a good idea because you'll get an explosion of these)
- a `Result<T>` or `UserOperationResult<T>` wrapper object that combines a response code constant (`ResultCode` or `UserOperationResultCode` respectively) and a return value `T`, or a wildcard `?` when there is no return value ... just watch out for pointcuts and the like that don't expect the wrapper)
The beauty of unchecked exceptions is that they avoid all this crap, but they come with their own set of issues. I'd personally stick to the last option, and have had decent luck with it in the past.
Problem
Are there some good practices to present service layer validation errors using Spring MVC after "shallow" user input validation has been performed using Spring MVC Validators? For example, having this code: ``` @Autowired private UserService userService; @RequestMapping(value = "user/new", method = RequestMethod.POST) public String createNewUser(@ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model){ UserFormValidator validator = new UserFormValidator(); //extending org.springframework.validation.Validator validator.validate(userForm, result); if(result.hasErrors()){ model.addAttribute("userForm", userForm); return "user/new"; } // here, for example, the user already might exist userService.createUser(userForm.getName(), userForm.getPassword()); return "redirect:user/home"; } ``` While it may seem trivial having this code as an example, it seems to be a delicate story to me when validation at service layer is a complex task. Despite being an absurd scenario, the UserService might take a list of users to create, and if one of them already exists, then the view tier must somehow be notified about which of them is not valid (e.g. does already exist). I am looking for a good practice how to design a piece of code, which makes it possible to 1) handle validation errors at the service layer having complex data as input, and 2) to present these validation errors to the user as easy as possible. Any suggestions?