I'm doing an error trapping with @ExceptionHandler but I'm not able to make this information available in the View.
Example I'm doing a group register. If the group already exists it throws an error. This error is handled and returns a ModelAndView. But I can not make the message available in $ {# fields.detailedErrors ()} of thymeleaf.
What am I doing?
First I created a RuntimeException extending error class.
public class GrupoRoleJaCadastradaException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Grupo grupo;
private BindingResult result;
public GrupoRoleJaCadastradaException(Grupo grupo,BindingResult result){
super();
this.grupo = grupo;
this.result = result;
}
public GrupoRoleJaCadastradaException(Grupo grupo,BindingResult result,String message){
super();
this.grupo = grupo;
this.result = result;
}
public Grupo getGrupo() {
return grupo;
}
public BindingResult getResult() {
return result;
}
}
Do not control when calling the service sending the Group object and the BindingResult where I will do the treatment.
@PostMapping("/grupos/novo")
public ModelAndView salvarNovo(@Valid Grupo grupo, BindingResult result, Model model,RedirectAttributes attributes,@AuthenticationPrincipal UsuarioSistema usuarioSistema ) {
if(result.hasErrors()){
return novoGrupo(grupo);
}
grupo = grupoService.salvar(grupo,result);
attributes.addFlashAttribute("mensagem", "Grupo salvo com sucesso");
return new ModelAndView("redirect:/administracao/grupos");
}
In Service I'm releasing the created error
public Grupo salvar(Grupo grupo, BindingResult result) {
throw new GrupoRoleJaCadastradaException(grupo,result);
//return grupoRep.save(grupo);
}
On the Controller, I intercept the posted error
@ExceptionHandler({GrupoRoleJaCadastradaException.class})
public ModelAndView handlerGrupoRoleJaCadastradaException(GrupoRoleJaCadastradaException ex){
grupoValidator.validate(ex.getGrupo(), ex.getResult() );
return novoGrupo(ex.getGrupo());
}
In the GroupValidator class I treat the error
@Override
public void validate(Object target, Errors errors) {
errors.rejectValue("role", " ", "teste de erro validate" );
}
And return a ModelAndView that shows the screen. - return newGroup (ex.Group ());
But the error does not reach the view.
I have tried several alternatives like adding the BindingResult object to the ModelAndView as below but it also did not work.
@ExceptionHandler({GrupoRoleJaCadastradaException.class})
public ModelAndView handlerGrupoRoleJaCadastradaException(GrupoRoleJaCadastradaException ex){
grupoValidator.validate(ex.getGrupo(), ex.getResult() );
return novoGrupo(ex.getGrupo(), ex.getResult());
}
private ModelAndView novoGrupo(Grupo grupo) {
ModelAndView mv = new ModelAndView("administracao/GrupoCadastro");
mv.addObject("grupo", grupo);
return mv;
}
private ModelAndView novoGrupo(Grupo grupo,BindingResult result) {
System.out.println("-----"+result);
return novo(grupo).addObject(result);
}
Note that I gave a sysout in the result and make sure the error is there.
But when displaying the page there is no error.
<H1>[[${#fields.hasAnyErrors()}]]</H1>
<div class="alert alert-danger alert-dismissible" role="alert" th:if="${#fields.hasAnyErrors()}" >
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span></button>
<th:block th:each="detailedError : ${#fields.detailedErrors()}">
<div><i class="fa fa-exclamation-circle"></i> [[${detailedError.message}]]</div>
</th:block>
</div>