Hey Neil,
good point. IIRC the BindingResult interface was created to be accessed from the controller only. Typically, a controller reads the BindingResult and then prepares some special model for parameter errors (and maybe other messages) which allows the view to access all the details. So you could implement a view model that can be used like shown in your example like this:
public class BindingModel {
private Set<ParamError> errors;
public BindingModel( BindingResult bindingResult ) {
this.errors = bindingResult.getAllErrors();
}
public boolean hasErrors(String paramName) {
return errors.stream()
.anyMatch( p -> p.getParamName().equals(paramName) );
}
public String error(String paramName) {
return errors.stream()
.filter( p -> p.getParamName().equals(paramName) )
.map(ParamError::getMessage)
.findFirst().orElse(null);
}
...
}
And in your controller:
if( bindingResult.isFailed() ) {
models.put("binding", new BindingModel(bindingResult));
return "view.jsp";
}
You can also use CDI models to make it a bit simpler. See this code in one of my example apps:
I'm not really sure about how to address this. Back then I proposed a "Messages" class which can be used to store arbitrary messages that need to be rendered (similar to the Messages class from my example), but the former spec leads voted against this. Such a messages class could also carry success messages which are also very common in web apps. So maybe this is somehow related.
There is also support for "messages" in the MVC Toolbox project, which contains some utilities for MVC apps. See:
To sum up. I'm not really sure if we found the optimal solution for this yet. And as we are close to the final release of the *first* spec version, I would prefer to target such an improvement for the next spec version. Especially because users can implement a solution which fits their needs best very easily them self.
Other thoughts?
Christian