Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Framework <form:errors/> tag not showing errors

I know there are many similar questions here, but none of them solved my problem.

I'm using Spring 4.0.3 and Hibernate Validator 5.1.0. The problem occurs when I try to omit the path attribute of the <form:errors/> tag, so:

<form:errors path="contato.nome" /> works
<form:errors path="*" /> works
<form:errors /> doesn't work

I don't know why it happens. Spring javadocs (org.springframework.web.servlet.tags.form.ErrorsTag) says it should work like that:

Field only - set path to the field name (or path)
Object errors only - omit path
All errors - set path to *

Can you help me, please?

The interested code is in the 'edicao.jsp' and in the method 'confirmarEdicao' of the ContatoController.java. Sorry if my english is bad.


ContatoController.java

@Controller
@RequestMapping("/contatos")
public class ContatoController {

    @Autowired
    private ContatoService contatoService;

    @Autowired 
    private MessageSource messageSource;

    @RequestMapping(value = "/confirmarEdicao", method = RequestMethod.POST)
    public String confirmarEdicao(@Valid Contato contato, BindingResult bindingResult) {

        if(bindingResult.hasErrors()) {
            return "contatos/edicao";
        }

        contatoService.save(contato);
        return "redirect:/contatos";
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView form(HttpServletRequest request) {
        String message = messageSource.getMessage("teste", null, new Locale("pt", "BR"));
        System.out.println(message);
        return new ModelAndView("contatos/listagem")
            .addObject("contatos", contatoService.list());
    }

    @RequestMapping("/remover/{id}")
    public String remover(Contato contato) {
        contatoService.delete(contato);
        return "redirect:/contatos";
    }

    @RequestMapping("/editar/{id}")
    public ModelAndView formEdicao(Contato contato) {
        contato = contatoService.find(contato.getId());
        return new ModelAndView("contatos/edicao")
            .addObject(contato);
    }


    @RequestMapping(value = "/cadastrar")
    public String formCadastro() {
        return "contatos/cadastro";
    }

    @RequestMapping(value = "/confirmarCadastro", method = RequestMethod.POST)
    public String confirmarCadastro(@Valid Contato contato, BindingResult bindingResult, 
            RedirectAttributes redirectAttributes) {        

        if (bindingResult.hasFieldErrors()) {
            return "contatos/cadastro";
        }

        contatoService.save(contato);
        redirectAttributes.addFlashAttribute("mensagem", "Contato cadastrado com sucesso.");
        return "redirect:/contatos";
    }   

    @ResponseBody
    @RequestMapping(value = "/pesquisar/{nome}", method = RequestMethod.GET, 
        produces="application/json")
    public List<Contato> pesquisar(@PathVariable String nome) {
        return contatoService.findByName(nome);
    }

}

edicao.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Editar contato</title>
</head>
<body>

<c:set var="context">${pageContext.request.contextPath}</c:set>
<script type="text/javascript">var context = "${context}";</script>
<script src="${context}/resources/js/jquery-2.1.0.min.js"></script>
<script src="${context}/resources/js/contatos/edicao.js"></script>

<form:form commandName="contato" action="${context}/contatos/confirmarEdicao" method="post">
<form:errors/>
    <table>
        <form:hidden path="id"/>
        <tr>
            <td>Nome:</td> 
            <td><form:input path="nome" /></td>
        </tr>
        <tr>
            <td>Telefone:</td>
            <td><form:input path="telefone"/></td>
        </tr>
        <tr>
            <td><input type="button" value="Voltar" id="btn_voltar"/><input type="submit" value="Salvar"/></td>         
        </tr>
    </table>
</form:form>

</body>
</html>

Contato.java

package com.handson.model;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;

public class Contato {

    private Long id;

    @Size(min = 3, message = "Nome deve ter no mínimo 3 caracteres")
    @NotEmpty(message = "O nome deve ser preenchido")
    private String nome;

    private String telefone;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }

    public Contato withId(Long id) {
        setId(id);
        return this;
    }

    public Contato withTelefone(String telefone) {
        setTelefone(telefone);
        return this;
    }

    public Contato withNome(String nome) {
        setNome(nome);
        return this;
    }

    @Override
    public String toString() {
        return "Contato [id=" + id + ", nome=" + nome + ", telefone="
                + telefone + "]";
    }

}
like image 754
lalsberg Avatar asked Apr 26 '14 21:04

lalsberg


People also ask

Which tag can render field validation errors?

The <errors> tag renders field errors in an HTML 'span' tag.

What is spring form commandName?

The commandName attribute is the most important attribute in the form tag, which specifies the model attribute name that contains a backing object and the properties of this object will be used to populate the generated form.

What is spring tag?

Spring tag LibraryIt exposes a binding path to inner tags for binding the data entered. It puts the command object in the PageContext so that the command object can be accessed by all the inner tags. All the other tags in the spring tag library are nested tags of this form tag.


1 Answers

There are some keywords which should be defined:

  • path - EL-like path to an object or to a field of an object (e.g. foo, foo.bar or foo.bar.baz)
  • nested path - current path context stored as nestedPath request attribute (new paths are relative to this path)
  • object error - error connected with object itself (e.g. path is equal to foo)
  • field error - error connected with object field (e.g. path is foo.bar)

The tag <form:form commandName="foo"> defines nested path as nestedPath=foo. When you write <form:errors path="bar"> it tries to find errors defined for path foo.bar.

Lets say that you have errors connected with foo (object error), foo.bar and foo.bar.baz (nested field error). What this means:

  • if you enter <form:errors>, only errors bound to foo path are displayed => 1 message
  • if you enter <form:errors path="bar">, only errors bound to foo.bar path are displayed => 1 message
  • if you enter <form:errors path="*">, errors bound to foo and its child paths are displayed => 3 messages
  • if you enter <form:errors path="bar.*">, only child errors for foo.bar are diplayed => 1 message
  • if you enter <form:errors path="bar*">, errors bound to foo.bar and its child paths are diplayed => 2 messages

Checking on Errors class JavaDoc might give you additional insight.

like image 182
Pavel Horal Avatar answered Dec 15 '22 18:12

Pavel Horal