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 + "]";
}
}
The <errors> tag renders field errors in an HTML 'span' tag.
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.
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.
There are some keywords which should be defined:
foo
, foo.bar
or foo.bar.baz
)nestedPath
request attribute (new paths are relative to this path)foo
)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:
<form:errors>
, only errors bound to foo
path are displayed => 1 message<form:errors path="bar">
, only errors bound to foo.bar
path are displayed => 1 message<form:errors path="*">
, errors bound to foo
and its child paths are displayed => 3 messages<form:errors path="bar.*">
, only child errors for foo.bar
are diplayed => 1 message<form:errors path="bar*">
, errors bound to foo.bar
and its child paths are diplayed => 2 messagesChecking on Errors
class JavaDoc might give you additional insight.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With