What is the purpose of spring model addObject(Object attributeName)? - spring

In spring mvc, when creating a ModelAndView there's a method called addObject(Object attributeName) single parameter, and I don't understand how to make use of it. I also see model.addAllObjects(Map<String, ?> object).
How can I get that map in jsp? Or what is the purpose of those methods? I only know how to make use of model.addObject("car", new Car()) because is like defining servlet parameters. I found this information in spring but I don't really understand it.
Spring addObject and addAllObjects

please check the example below. i have shed how to use addObject(Object attributeValue) as well as addAllObjects(Map<String, ?> modelMap).
Car.java
public class Car {
private String regNo;
private String model;
private String year;
public String getRegNo() {
return regNo;
}
public void setRegNo(String regNo) {
this.regNo = regNo;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
}
PageContent.java
public class PageContent {
private String headerName;
public String getHeaderName() {
return headerName;
}
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
}
Controller Method
#RequestMapping(value = "/showCars", method = RequestMethod.GET)
public ModelAndView showApp() {
ModelAndView modelAndView = new ModelAndView();
//adding a single attribute for the modelMap
PageContent pageContent = new PageContent();
pageContent.setHeaderName("All Cars - From Controller");
modelAndView.addObject(pageContent);
List<Car> carList = new ArrayList<>();
Car car1 = new Car();
car1.setModel("Toyota");
car1.setRegNo("223456");
car1.setYear("2005");
Car car2 = new Car();
car2.setModel("Mazda");
car2.setRegNo("24244");
car2.setYear("2015");
Car car3 = new Car();
car3.setModel("Nissan");
car3.setRegNo("4465757");
car3.setYear("2013");
carList.add(car1);
carList.add(car2);
carList.add(car3);
Map<String,Object> allObjectsMap = new HashMap<String,Object>();
allObjectsMap.put("allCarObjects", carList);
//adding a set of objects for the model map
modelAndView.addAllObjects(allObjectsMap);
modelAndView.setViewName("CarView");
return modelAndView;
}
CarView.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<title>ModelAttribute Example</title>
</head>
<body>
<h1>${pageContent.headerName}</h1>
<table>
<tr>
<th>Model</th>
<th>Registration No</th>
<th>Year of Manufacture</th>
</tr>
<c:forEach var="car" items="${allCarObjects}">
<tr>
<td><c:out value="${car.model}" /></td>
<td><c:out value="${car.regNo}" /></td>
<td><c:out value="${car.year}" /></td>
</tr>
</c:forEach>
</table>
</body>
</html>
Hope this will helpful for you!

well,the first method addObject which would invoked when forward happend and brings the data to jsp.Then you can iterate the data in your jsp with jstl or something else.The method addAllObjects is just a multiple type of addObject,just like map's method put and putAll.

Related

Add student without avatar

I created a project where you can add a student with an avatar and without an avatar. The problem is that when I add a student without an avatar, there is still a tag. How can I remove the tag. Now I will add an image and a couple of classes. I kind of wrote everything correctly, I don’t know where the error might be
#Controller
public class AvatarController {
#Value("${storage.location}")
private String storageLocation;
private StudentService studentService;
#Autowired
private ServletContext servletContext;
// Constructor based Dependency Injection
#Autowired
public AvatarController(StudentService studentService) {
this.studentService = studentService;
}
#GetMapping(value = "/avatar")
public void getAvatar(HttpServletResponse response, #Param("avatar") String avatar) {
if (avatar == null || avatar.isEmpty()) {
return;
}
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
try (FileInputStream input = new FileInputStream(studentService.loadAvatarByFileName(avatar))){
IOUtils.copy(input, response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
#RequestMapping(value = "/image", method = RequestMethod.GET)
public void image(#RequestParam String url, HttpServletResponse response) throws IOException {
InputStream in = new FileInputStream(url);
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
IOUtils.copy(in, response.getOutputStream());
}
}
Student Service Impl
#Service
#Transactional
public class StudentServiceImpl implements StudentService {
#Value("${storage.location}")
private String storageLocation;
private StudentRepository repository;
public StudentServiceImpl() {
}
#Autowired
public StudentServiceImpl(StudentRepository repository) {
super();
this.repository = repository;
}
#Override
public List<Student> getAllStudents() {
List<Student> list = new ArrayList<Student>();
repository.findAll().forEach(e -> list.add(e));
return list;
}
#Override
public Student getStudentById(Long id) {
Student student = repository.findById(id).get();
return student;
}
#Override
public boolean saveStudent(Student student) {
try {
repository.save(student);
return true;
} catch (Exception ex) {
return false;
}
}
#Override
public boolean deleteStudentById(Long id) {
try {
repository.deleteById(id);
return true;
} catch (Exception ex) {
return false;
}
}
#Override
public File loadAvatarByFileName(String filename) {
return new File(storageLocation + "/" + filename);
}
#Override
public File saveAvatarImage(MultipartFile avatarImage) throws IOException {
File newFile = File.createTempFile(
avatarImage.getName(),
"." + avatarImage.getOriginalFilename().split("\\.")[1],
new File(storageLocation));
avatarImage.transferTo(newFile);
return newFile;
}
#Override
public Student updateStudent(String name, String surname, MultipartFile avatar, Student targetStudent)
throws IOException {
if (name != null && !name.equals(targetStudent.getName())) {
targetStudent.setName(name);
}
if (surname != null && !surname.equals(targetStudent.getSurname())) {
targetStudent.setSurname(surname);
}
File newAvatar;
if (!avatar.getOriginalFilename().isEmpty()) {
if (targetStudent.getAvatar() != null) {
Files.deleteIfExists(Paths.get(storageLocation + File.separator + targetStudent.getAvatar()));
}
newAvatar = saveAvatarImage(avatar);
assert newAvatar != null;
targetStudent.setAvatar(newAvatar.getName());
}
boolean isSaved = saveStudent(targetStudent);
if (!isSaved) {
throw new IOException();
}
return targetStudent;
}
}
Student Controller
#Controller
public class StudentController {
#Autowired
private ServletContext servletContext;
// Constructor based Dependency Injection
private StudentService studentService;
public StudentController() {
}
#Autowired
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
#RequestMapping(value = "/allStudents", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView displayAllUser() {
System.out.println("User Page Requested : All Students");
ModelAndView mv = new ModelAndView();
List<Student> studentList = studentService.getAllStudents();
mv.addObject("studentList", studentList);
mv.setViewName("allStudents");
return mv;
}
#Secured("ROLE_ADMIN")
#RequestMapping(value = "/allStudentsAdmin", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView displayAllUsers() {
System.out.println("User Page Requested : All Students");
ModelAndView mv = new ModelAndView();
List<Student> studentList = studentService.getAllStudents();
mv.addObject("studentList", studentList);
mv.setViewName("allStudentsUser");
return mv;
}
#Secured("ROLE_USER")
#RequestMapping(value = "/allStudentsUser", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView displayAllUsers() {
System.out.println("User Page Requested : All Students");
ModelAndView mv = new ModelAndView();
List<Student> studentList = studentService.getAllStudents();
mv.addObject("studentList", studentList);
mv.setViewName("allStudentsUser");
return mv;
}
#RequestMapping(value = "/addStudent", method = RequestMethod.GET)
public ModelAndView displayNewUserForm() {
ModelAndView mv = new ModelAndView("addStudent");
mv.addObject("headerMessage", "Add Student Details");
mv.addObject("student", new Student());
return mv;
}
#PostMapping(value = "/addStudent")
public String saveNewStudent(#RequestParam("name") #NonNull String name,
#RequestParam("surname") #NonNull String surname,
#RequestParam("avatar") MultipartFile file)
throws IOException {
Student student = new Student();
student.setSurname(surname);
student.setName(name);
if (file != null && !file.isEmpty()) {
student.setAvatar(studentService.saveAvatarImage(file).getName());
}
studentService.saveStudent(student);
return "redirect:/allStudents";
}
#GetMapping(value = "/editStudent/{id}")
public ModelAndView displayEditUserForm(#PathVariable Long id) {
ModelAndView mv = new ModelAndView("editStudent");
Student student = studentService.getStudentById(id);
mv.addObject("headerMessage", "Редактирование студента");
mv.addObject("student", student);
return mv;
}
#PostMapping(value = "/editStudent")
public String saveEditedUser(
#RequestParam("id") Long id,
#RequestParam("name") String name,
#RequestParam("surname") String surname,
#RequestParam("avatar") MultipartFile file) {
try {
studentService.updateStudent(name, surname, file, studentService.getStudentById(id));
} catch (FileSystemException ex) {
ex.printStackTrace();
} catch (IOException e) {
return "redirect:/error";
}
return "redirect:/allStudents";
}
#GetMapping(value = "/deleteStudent/{id}")
public ModelAndView deleteUserById(#PathVariable Long id) {
studentService.deleteStudentById(id);
ModelAndView mv = new ModelAndView("redirect:/allStudents");
return mv;
}
}
AllStudent JSP
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<!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">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<link href="../css/style.css" rel="stylesheet" type="text/css">
<style><%#include file="/css/style.css"%></style>
<title>Все студенты</title>
</head>
<body>
<br>
<br>
<br>
<br>
<div class="it">
<h3>Список всех студентов</h3>
${message}
<br>
<br>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Surname</th>
<th scope="col">Avatar</th>
</tr>
</thead>
<tbody>
<c:forEach var="student" items="${studentList}">
<tr>
<th scope="row">1</th>
<td>${student.name}</td>
<td>${student.surname}</td>
<td><c:choose>
<c:when test="${student.avatar ne null}">
<td>
<img src="${pageContext.request.contextPath}/avatar?avatar=${student.avatar}"
style="max-height: 200px; max-width: 200px;" />
</td>
</c:when>
</c:choose></td>
<td>
<sec:authorize access="hasRole('ADMIN')">
<a href="${pageContext.request.contextPath}/editStudent/${student.id}">
<button type="button" class="btn btn-primary">Edit</button>
</a>
</sec:authorize>
</td>
<td>
<sec:authorize access="hasRole('ADMIN')">
<a href="${pageContext.request.contextPath}/deleteStudent/${student.id}">
<button type="button" class="btn btn-primary">Delete</button>
</a>
</sec:authorize>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</body>
</html>
#user404 answer ok but need some change
<c:choose>
<c:when test="${student.avatar ne null}">
<td>
<img src="${pageContext.request.contextPath}/avatar?avatar=${student.avatar}"
style="max-height: 200px; max-width: 200px;" />
</td>
</c:when>
<c:otherwise>
<td></td>
</c:otherwise>
</c:choose>
despription : When avater is null or empty then add a empty cell on
our html table other wise add image with full src path
You have to check the condition if your student.avatar holds avatar or null and based on that, show your image or not. Coz, that image tag for empty avatar your see because of img tag. You can use if-else condition in jstl or like this.
try this:
<c:choose>
<c:when test="${student.avatar ne null}">
<td>
<img src="${pageContext.request.contextPath}/avatar?avatar=${student.avatar}"
style="max-height: 200px; max-width: 200px;" />
</td>
</c:when>
<c:otherwise>
<td></td>
</c:otherwise>
</c:choose>

"Neither BindingResult nor plain target object for bean name 'command' available as request attribute"

I am getting an exception while creating a form using spring forms tag library
"Neither BindingResult nor plain target object for bean name 'command' available as request attribute"
The jsp page is index.jsp
<%# include file="views/static_include.jsp" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!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=ISO-8859-1">
<title>Login to AVA Corp</title>
</head>
<body>
<form:form method="POST" commandName="user" action="login.jsp">
<table>
<tbody><tr>
<td><form:label path="firstName">Name:</form:label></td>
<td><form:input path="firstName"></form:input></td>
</tr>
<tr>
<td><form:label path="age">Age:</form:label></td>
<td><form:input path="age"></form:input></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit">
</td>
<td></td>
<td></td>
</tr>
</tbody></table>
</form:form>
</body>
</html>
The bean class is:
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1949001721422434327L;
private String firstName;
private Integer age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
The controller class is
#Controller
public class LoginController {
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView initForm(Model model) {
return new ModelAndView("index", "user", new Employee());
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(#ModelAttribute("user") Employee employee, BindingResult result, SessionStatus status){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user", employee);
return "UserFormSuccess";
}
}
I found that the issue was with the controller method with method type = "get". The value of the request method needs to be the URL mapping of the page on which the form resides e.g. index.jsp in our case so the controller class will be
#Controller
public class LoginController {
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView initForm(Model model) {
return new ModelAndView("index", "user", new Employee());
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(#ModelAttribute("user") Employee employee, BindingResult result, SessionStatus status){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user", employee);
return "UserFormSuccess";
}
}

Binding form parameters from JSP to spring controller

I know this is a question which has been asked before. I did look at those questions but I was still not able to resolve my problem and thus writing in on stackoverflow. I am trying to bind the form parameters from my form addArticles.jsp to the controller. On the controller when I do a system.out.println I only get the categoryId and do not get the categoryName. I am not sure what I am doing is incorrect and pretty amused.
addArticles.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!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=ISO-8859-1">
<title>Add Article</title>
</head>
<body>
<center>
<h2>Create New Article</h2>
<form:form action="/one2one/articles/save.do" method="POST" modelAttribute="command">
<table>
<tr>
<td><form:label path="id">Article ID</form:label></td>
<td><form:input path="id" value="${article.id}"></form:input></td>
</tr>
<tr>
<td><form:label path="title">Article Title</form:label></td>
<td><form:input path="title" value="${article.title}"></form:input></td>
</tr>
<tr>
<td><form:label path="description">Article Description:</form:label></td>
<td><form:input path="description" value="${article.description}" cssStyle="width: 150px;"></form:input></td>
</tr>
<tr>
<td><form:label path="category.categoryId">Category Type</form:label></td>
<td><form:select path="category.categoryId" cssStyle="width: 150px;">
<option value="-1">Select a type</option>
<c:forEach items="${categories}" var="category">
<option <c:if test="${category.categoryName eq article.category.categoryName}">selected="selected"</c:if>
value="${category.categoryId}">${category.categoryName}</option>
</c:forEach>
</form:select>
</td>
</tr>
<tr>
<td><form:label path="keywords">Article Keywords:</form:label></td>
<td><form:input path="keywords" value="${article.keywords}"></form:input></td>
</tr>
<tr>
<td><form:label path="content">Article Content:</form:label></td>
<td><form:input path="content" value="${article.content}"></form:input></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="SAVE"/></td>
</tr>
</table>
</form:form>
</center>
</body>
</html>
ArticlesController.java
package com.java.bricks.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.java.bricks.model.Article;
import com.java.bricks.model.Category;
import com.java.bricks.service.ArticleService;
import com.java.bricks.service.CategoryService;
#Controller("articlesController")
#RequestMapping(value="/articles")
public class ArticlesController {
#Autowired
private ArticleService articleService;
#Autowired
private CategoryService categoryService;
#RequestMapping(value="/list", method=RequestMethod.GET)
public ModelAndView listArticles(#ModelAttribute("command") Article article, BindingResult bindingResult){
Map<String,Object> model = new HashMap<String,Object>();
model.put("articles", articleService.listArticles());
return new ModelAndView("articlesList",model);
}
#RequestMapping(value="/add",method=RequestMethod.GET)
public ModelAndView addArticle(#ModelAttribute("command") Article article, BindingResult bindingResult) {
Map<String,Object> model = new HashMap<String,Object>();
model.put("articles", articleService.listArticles());
model.put("categories", categoryService.listCategories());
return new ModelAndView("addArticle",model);
}
#RequestMapping(value="/save",method=RequestMethod.POST)
public ModelAndView saveArticle(#ModelAttribute("command") Article article, BindingResult bindingResult) {
Map<String,Object> model = new HashMap<String,Object>();
System.out.println("----------------------");
System.out.println(article.getCategory());
System.out.println(article.getCategory().getCategoryName());
System.out.println(article.getCategory().getCategoryId());
articleService.addArticle(article);
model.put("articles",articleService.listArticles());
return new ModelAndView("addArticle",model);
}
}
when I click save the first 4 lines of the SOP statements are
System.out.println(article.getCategory());
output: Category [categoryId=29, categoryName=null]
System.out.println(article.getCategory().getCategoryName());
null
System.out.println(article.getCategory().getCategoryId())
29
I am not sure why the categoryName is not populated in the controller.
Article.java
package com.java.bricks.model;
public class Article {
private Long id;
private String title;
private String description;
private String keywords;
private String content;
private Category category;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getKeywords() {
return keywords;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
}
You aren't going to get the category name in the form's content because the category's name is being used a the label for the option. Only the value gets bound. This is your binding path="category.categoryId". You aren't binding anything to path="category.categoryName" so it's going to be null.
So in your controller you have to get the category by its ID. If you want to do some automatic custom conversion, that is a separate question.
Here's a nice article on entity conversion.

Form POST submit "The request sent by the client was syntactically incorrect."

I have no idea where I've made a mistake. I've been trying to solve this problem for hours but can't figure it out...
I'm getting HTTP Status 400 The request sent by the client was syntactically incorrect. while submiting the form with list of objects with some checkboxes to each of the objects.
Heres some of the code:
Controller:
#RequestMapping(value = "/admin/panel", method = RequestMethod.GET)
public String adminPanel(Locale locale, Model model, Form form,
HttpServletRequest request) {
FormWrapper wrapper = getFormWrapper();
model.addAttribute("listOfObjects", wrapper);
model.addAttribute("allCategories", dao.getCatsList());
return "WEB-INF/views/index/admin/home";
}
#RequestMapping(value = "/admin/saveAdmin", method = RequestMethod.POST)
public String save(Model model, #ModelAttribute(value="listOfObjects") FormWrapper listOfObjects) {
return "redirect:../index.html";
}
JSP:
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<form:form modelAttribute="listOfObjects" method="POST" action="/admin/saveAdmin">
<c:forEach var="myObject" items="${listOfObjects.list}" varStatus="loop">
<form:checkboxes items="${allCategories}" path="list[${loop.index}].selectedCategories" itemLabel="name"/>
</c:forEach>
<input type="submit" value="saveTest"/>
</form:form>
FormWrapper:
public class FormWrapper {
private List<Form> list;
public List<Form> getList() {
return list;
}
public void setList(List<Form> list) {
this.list = list;
}
}
Category:
public class Category{
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long categoryId;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getCategoryId() {
return categoryId;
}
public void setCategoryId(Long categoryId) {
this.categoryId = categoryId;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Category){
return getCategoryId().equals(((Category)obj).getCategoryId());
} else {
return false;
}
}
}
Any help is appreciated. I tried to change the model attribute adnotatnion to RequestParam , but in such case , my object is always null
Is it because, the FormWrapper class do not have a property "selectedCategories".
I tried removing the "selectedCategories"
Then the form was submitted successfully.
<form:checkboxes items="${allCategories}" path="list[${loop.index}]" itemLabel="name"/>
I'm not sure I understand your jsp correctly but this problem occurs when something in the jsp form does not match with the parameters you're handling at the controller.
Are you sure that "path" variable below is ok?
<form:checkboxes items="${allCategories}" path="list[${loop.index}].selectedCategories" itemLabel="name"/>

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 + "]";
}
}
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.

Resources