how to use javax.validation with Thymeleaf - validation

When I run this it will create a new book if valid however upon error it will not post back to the page and I get a 400:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='book'. Error count: 4
I tested with system outs, it never gets to the submit if it has errors, I think maybe #Valid is wrong or ???
This is my controller... please tell me what's missing ?
#Controller
#RequestMapping("/")
public class BookController{
#RequestMapping(method=RequestMethod.GET)
public String home(Model model) {
refData = new ReferenceData();
model.addAttribute("refData", refData);
model.addAttribute("book", new Book());
List<Book> books = BookRepo.findAll();
model.addAttribute("books", books);
return "home";
}
#RequestMapping(method=RequestMethod.POST)
public String submit(#Valid Book book,Model model, BindingResult bindingResult) {
refData = new ReferenceData();
model.addAttribute("refData", refData);
if (bindingResult.hasErrors()) {
return "home";
}
BookRepo.save(book);
return "redirect:/";
}
My form looks like this...
<form name="addForm" action="#" th:action="#{/}" th:object="${book}" method="post">
<table>
<tr>
<td><label for="*{title}">Book:</label></td>
<td><input type="text" th:field="*{title}" /></td>
<td th:if="${#fields.hasErrors('title')}" th:errors="*{title}">Name
Error</td>
</tr>
<tr>
<td><label for="*{author}">Author:</label></td>
<td><input type="text" th:field="*{author}" /></td>
<td th:if="${#fields.hasErrors('author')}" th:errors="*{author}">Author
Error</td>
</tr>
<tr>
<td><label for="*{genre}">Genre:</label></td>
<td><input type="text" th:field="*{genre}" /></td>
<td th:if="${#fields.hasErrors('genre')}" th:errors="*{genre}">genre
Error</td>
</tr>
<tr>
<td><label for="*{pages}">Pages:</label></td>
<td><input type="text" th:field="*{pages}" /></td>
<td th:if="${#fields.hasErrors('pages')}" th:errors="*{pages}">pages
Error</td>
</tr>
<tr>
<td><label th:for="*{year}">Year:</label></td>
<td>
<select th:field="*{year}" ng-model="bookData.year">
<option th:each="selectItem: ${refData.years}"
th:value="${selectItem.value}" th:text="${selectItem.label}">year</option>
</select>
</td>
<td th:if="${#fields.hasErrors('year')}" th:errors="*{year}">year
Error</td>
</tr>
<tr>
<td><label th:for="*{rating}">Rating:</label></td>
<td><select th:field="*{rating}" ng-model="bookData.rating">
<option th:each="selectItem: ${refData.rating}"
th:value="${selectItem.value}" th:text="${selectItem.label}">rating</option>
</select></td>
<td th:if="${#fields.hasErrors('rating')}" th:errors="*{rating}">rating
Error</td>
</tr>
<tr>
<td><button type="submit">Submit</button></td>
</tr>
</table>
</form>
my entity...
#Entity
public final class Book
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
#Pattern(regexp="^[a-zA-Z0-9_]+$")
private String title;
#NotNull
#Pattern(regexp="^[a-zA-Z0-9_]+$")
private String author;
#NotNull
#Pattern(regexp="^[a-zA-Z0-9_]+$")
private String genre;
#NotNull
#Digits(message="message here", integer=32767, fraction = 0)
private Integer pages;
private String year;
private String rating;

I found I had to place the bindingResult directly after the #Valid Book entity thus...
#RequestMapping(method=RequestMethod.POST)
public String submit(#Valid Book book,**BindingResult bindingResult**, Model model ) {
refData = new ReferenceData();
model.addAttribute("refData", refData);
if (bindingResult.hasErrors()) {
return "home";
}
BookRepo.save(book);
return "redirect:/";
}
Wow what a minor=major mistake !!
Johnny O.

Related

Spring MVC: Neither BindingResult nor plain target object for bean name 'marks' available as request attribute. Tried all solutions

I tried all the solutions but I keep getting this error. Moreover if i don't use form:form in jsp file and use a simple HTML, I get the desired output.
Controller Class
#Controller
public class controller_class {
/*
* #RequestMapping(path = "/index", method = RequestMethod.GET) public
* ModelAndView mar() { return new ModelAndView("index","command",new marks());
* }
*/
#RequestMapping("/index")
public ModelAndView showComments() {
return new ModelAndView("marks","command",new marks());
}
#RequestMapping(value = "/addMarks", method = RequestMethod.POST)
public ModelAndView stud(#ModelAttribute("marks") marks m) {
ModelAndView mv = new ModelAndView("result");
int k = m.calculate();
mv.addObject("tot_marks", k);
return mv;
}
}
index.jsp
<form:form method = "POST" modelAttribute="marks" action = "/springmvc_qa3/addMarks">
<table>
<tr>
<td><form:label path = "sci_marks">Name</form:label></td>
<td><form:input path = "sci_marks" /></td>
</tr>
<tr>
<td><form:label path = "maths_marks">Age</form:label></td>
<td><form:input path = "maths_marks" /></td>
</tr>
<tr>
<td><form:label path = "eng_marks">id</form:label></td>
<td><form:input path = "eng_marks" /></td>
</tr>
<tr>
<td colspan = "2">
<input type = "submit" value = "Submit"/>
</td>
</tr>
</table>
</form:form>
</body>
Correct Output if I use this instead
<form method="POST" action="/springmvc_qa3/addMarks" >
<table>
<tr>
<td><label >Science Marks</label></td>
<td><input type="text" name="sci_marks" /></td>
</tr>
<tr>
<td><label >Mathematics Marks</label></td>
<td><input type="text" name="maths_marks" /></td>
</tr>
<tr>
<td><label >English Marks</label></td>
<td><input type="text" name="eng_marks" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
</td>
</tr>
</table>
</form>
What is the reason that I can't get the right output using the first method?
add the following to your controller class:
#ModelAttribute("marks")
public Marks nameOfMethodDoesntMatter(){
return new Marks();
}
make sure your Marks class has getters, setters and default constructor.
consider calling your class MarksDTO or something similar to convey its meaning better (DTO = data transfer object).

Inconsistent of adding and deleting data

I'm currently having inconsistent of adding and deleting data which happen randomly without any errors showing. The page will just keep loading forever until I stop my tomcat server. I can't identify where is the problem which is causing this inconsistency.
Controller
#RequestMapping(value = "menu/{userId}", method = RequestMethod.GET)
public ModelAndView orderPizzaForm(#ModelAttribute(value = "pizzaform") PizzaTO pizzaTO,
#PathVariable String userId) {
ModelAndView model = new ModelAndView("pizzaform");
List pizzaList = pizzaService.getListByUserId(userId);
model.addObject("pizzaList", pizzaList);
return model;
}
#RequestMapping(value = "menu/add/{userId}", method = RequestMethod.POST)
public ModelAndView orderPizza(#ModelAttribute(value = "pizzaform") PizzaTO pizzaTO, #PathVariable String userId,
BindingResult result) {
ModelAndView model = new ModelAndView("pizzaform");
pizzaFormValidator.validate(pizzaTO, result);
if (result.hasErrors()) {
List pizzaList = pizzaService.getListByUserId(userId);
model.addObject("pizzaList", pizzaList);
return model;
} else {
pizzaTO.setUserId(userId);
String[] data = pizzaTO.getPizzaSize().split("\\|");
pizzaTO.setPizzaSize(data[0]);
pizzaTO.setPizzaPrice(Double.parseDouble(data[1]));
pizzaService.addPizza(pizzaTO);
List pizzaList = pizzaService.getListByUserId(userId);
model.addObject("pizzaList", pizzaList);
return model;
}
}
////////////////////////////// DELETE PIZZA //////////////////////////////
#RequestMapping(value = "menu/delete/{userId}/{pizzaId}", method = RequestMethod.GET)
public ModelAndView editEmployee(#ModelAttribute(value = "pizzaform") PizzaTO pizzaTO, #PathVariable String pizzaId,
#PathVariable("userId") String userId) {
pizzaService.deletePizza(pizzaId);
ModelAndView model = new ModelAndView("pizzaform");
List pizzaList = pizzaService.getListByUserId(userId);
model.addObject("pizzaList", pizzaList);
return model;
}
pizzaform.jsp
<body>
<div style="text-align: center">
<form:form commandName="pizzaform"
action="${pageContext.request.contextPath}/menu/add/${userId}" method="POST">
<form:hidden path="userId" value="${userId}" />
<table align="center">
<tr>
<td><label id="pizzaCrust">Choose a crust:</label></td>
<td><form:radiobutton path="pizzaCrust" value="Hand Tossed" />Hand
Tossed <form:radiobutton path="pizzaCrust" value="Thin Crust" />Thin
Crust<form:errors
path="pizzaCrust" class="error" /></td>
</tr>
<tr>
<td><label id="pizzaFlavour">Choose a flavour:</label></td>
<td><form:radiobutton path="pizzaFlavour" value="Pepperoni" />Pepperoni
<form:radiobutton path="pizzaFlavour" value="BBQ Chicken" />BBQ
Chicken <form:radiobutton path="pizzaFlavour"
value="Spicy Chicken" />Spicy Chicken<form:errors
path="pizzaFlavour" class="error" /></td>
</tr>
<tr>
<td><label id="pizzaSize">Choose a size:</label></td>
<td><form:radiobutton path="pizzaSize" value="10|23.80" />10 inch (Regular - 4 Pax)
<form:radiobutton path="pizzaSize" value="12|30.80" />12 inch (Medium - 6 Pax)
<form:radiobutton path="pizzaSize" value="14|37.80" />14 inch (Large - 8 Pax)<form:errors
path="pizzaSize" class="error" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Add" />
<button type="button" name="back"
onclick="window.location='${pageContext.request.contextPath}/main'">Back</button></td>
</tr>
</table>
</form:form>
<br> <br>
<table border="1" bgcolor="black" width="600px" align="center">
<tr
style="background-color: white; color: black; text-align: center;"
height="30px">
<td><b>Crust</b></td>
<td><b>Flavor</b></td>
<td><b>Size (Inch)</b></td>
<td><b>Price (S$)</b></td>
<td></td>
</tr>
<c:forEach items="${pizzaList}" var="pizza">
<tr
style="background-color: white; color: black; text-align: center;"
height="30px">
<td><c:out value="${pizza.pizzaCrust}" /></td>
<td><c:out value="${pizza.pizzaFlavour}" /></td>
<td><c:out value="${pizza.pizzaSize}" /></td>
<td><c:out value="${pizza.pizzaPrice}" /></td>
<td>Delete</td>
</tr>
</c:forEach>
</table>
</div>

Hibernate Spring - One to many

I am working on a JEE school project which is done with Spring and Hibernate. My tables are :
INFRACTION
id_infraction
description
DOSSIER
id_dossier
description
gravite
INFRACTIONDOSSIER
id_dossier
id_infraction
The application does work well for adding "infractions" and "dossiers" and retrieve them in jsp pages.
The app should be able to add multiple "infractions" to one "dossier", and that is where i'm blocked;
I'm learning One-to-many tags and implemented them in my "Dossier" Class, but as I want a form separated from the adding infraction and adding dossier ones, I don't know how to handle that.
Here is the code I added in my Dossier class :
#OneToMany
private Set<Infraction> infractions;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "DOSSIERINFRACTION",
joinColumns = #JoinColumn(name = "id_dossier"),
inverseJoinColumns = #JoinColumn(name = "id_infraction")
)
And my AppController class part handling adding Dossiers
/*
* Méthode d'ajout d'un dossier
*/
#RequestMapping(value = { "/new" }, method = RequestMethod.GET)
public String newDossier(ModelMap model) {
Dossier dossier = new Dossier();
model.addAttribute("dossier", dossier);
model.addAttribute("edit", false);
return "registration";
}
/*
* Gère l'envoi du POST pour l'ajout de dossier ainsi que la validation du
* formulaire
*
*/
#RequestMapping(value = { "/new" }, method = RequestMethod.POST)
public String saveDossier(#Valid Dossier dossier, BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "registration";
}
service.saveDossier(dossier);
model.addAttribute("success", "Dossier " + dossier.getNom() + " enregistré");
return "success";
}
JSP form to record a dossier
<form:form method="POST" modelAttribute="dossier">
<form:input type="hidden" path="id" id="id"/>
<table>
<tr>
<td><label for="nom">Nom: </label> </td>
<td><form:input path="nom" id="nom"/></td>
<td><form:errors path="nom" cssClass="error"/></td>
</tr>
<tr>
<td><label for="prenom">Prénom: </label> </td>
<td><form:input path="prenom" id="prenom"/></td>
<td><form:errors path="prenom" cssClass="error"/></td>
</tr>
<tr>
<td><label for="plaque">Plaque: </label> </td>
<td><form:input path="plaque" id="plaque"/></td>
<td><form:errors path="plaque" cssClass="error"/></td>
</tr>
<tr>
<td><label for="permis">Permis: </label> </td>
<td><form:input path="permis" id="permis"/></td>
<td><form:errors path="permis" cssClass="error"/></td>
</tr>
<tr>
<td colspan="3">
<c:choose>
<c:when test="${edit}">
<input type="submit" value="Mettre à jour"/>
</c:when>
<c:otherwise>
<input type="submit" value="Enregistrer"/>
</c:otherwise>
</c:choose>
</td>
</tr>
</table>
</form:form>
My question may seem a bit dumb, but how can I create a form which can add multiple infractions to dossier, and how to display the infractions from a dossier ?
Thank you,
Romain

Spring MVC Form Validation Neither BindingResult nor plain target object for bean name 'BanqueForm' available as request attribute

I have a probleme when validating a form with spring MVC
i have this exception
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'BanqueForm' available as request attribute
this is my controller
package org.gestion.banque.controllers;
import java.util.Map;
import javax.validation.Valid;
import org.gestion.banque.entities.Compte;
import org.gestion.banque.metier.IBanqueMetier;
#Controller
public class BanqueController {
#Autowired
private IBanqueMetier metier;
#RequestMapping(value="/index",method=RequestMethod.GET)
public String index(Model model){
model.addAttribute("BanqueForm", new BanqueForm());
return"banque";
}
#RequestMapping(value="/chargerCompte", method=RequestMethod.GET)
public String charger(Model m) {
m.addAttribute("BanqueForm", new BanqueForm());
return "banque";
}
#RequestMapping(value="/chargerCompte",method=RequestMethod.POST)
public String charger(#Valid BanqueForm bf,
BindingResult result,Model model){
if(result.hasErrors())
{
return "banque";
}
try {
Compte c=metier.ConsulterCompte(bf.getCode());
bf.setTypeCompte(c.getClass().getSimpleName());
bf.setCompte(c);
} catch (Exception e) {
bf.setException(e.getMessage());
}
model.addAttribute("BanqueForm", bf);
return "banque";
}
}
and this is my view
<body>
<div>
<f:form modelAttribute="BanqueForm" method="post" action="chargerCompte" >
<table>
<tr>
<td>Code :</td>
<td><f:input path="code"/></td>
<td><f:errors path="code"></f:errors> </td>
</tr>
<tr>
<td>
<input type="submit" value="OK" />
</td>
</tr>
</table>
</f:form>
</div>
<c:if test="${ not empty BanqueForm.exception}">
<div>${BanqueForm.exception} </div>
</c:if>
<c:if test="${not empty BanqueForm.compte}">
<div>
<table>
<tr>
<td>Solde :</td>
<td>${BanqueForm.compte.solde}</td>
</tr>
<tr>
<td>Solde :</td>
<td>${BanqueForm.compte.dateCreation}</td>
</tr>
<tr>
<td>Type de Compte :</td>
<td>${BanqueForm.typeCompte}</td>
</tr>
<c:if test="${BanqueForm.typeCompte=='CompteCourant'}">
<tr>
<td>Decouvert :</td>
<td>${BanqueForm.compte.decouvert}</td>
</tr>
</c:if>
<c:if test="${BanqueForm.typeCompte=='CompteEpargne'}">
<tr>
<td>taux :</td>
<td>${BanqueForm.compte.taux}</td>
</tr>
</c:if>
</table>
</div>
</c:if>
</body>
</html>
Add #ModelAttribute("BanqueForm") annotation when obtaining BanqueForm object. Something like this:
public String charger(#Valid #ModelAttribute("BanqueForm") BanqueForm bf,
BindingResult result, Model model) { ... }

can someone explain how the controller class works

I am working on spring samples.I have a controller class named UserController2 as follows
#Controller
public class UserController2 extends MultiActionController {
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
#RequestMapping(params = "add", method = RequestMethod.POST)
public ModelAndView add(HttpServletRequest request,
HttpServletResponse response, User user) throws Exception {
userDAO.saveUser(user);
return new ModelAndView("redirect:User.htm");
}
public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("userList", userDAO.listUser());
modelMap.addAttribute("User", new User());
return new ModelAndView("userForm", modelMap);
}
}
and i have a jsp page called userForm.jsp
<form:form method="POST" action="add.htm" commandName="User" modelAttribute="User">
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td><form:label path="id">id</form:label></td>
<td><form:input path="id" /></td>
</tr>
<tr>
<td><form:label path="password">Name</form:label></td>
<td><form:input path="password" /></td>
</tr>
<tr>
<td><form:label path="gender">Name</form:label></td>
<td><form:input path="gender" /></td>
</tr>
<tr>
<td><form:label path="gender">Name</form:label></td>
<td><form:input path="gender" /></td>
</tr>
<tr>
<td><form:label path="country">Name</form:label></td>
<td><form:input path="country" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
what actually does the below codes returns
return new ModelAndView("userForm", modelMap);
and
return new ModelAndView("redirect:User.htm");
I am getting the following error
java.lang.IllegalStateException: Neither BindingResult nor plain target object for
bean name 'User' available as request attribute
I searched but i cannot find a proper explanation for modelandview..
When using the modelAttribute make user that:1. Your method parameter user is annotated with #ModelAttribute("user")2. A method parameter of type BindingResult is declared.
Also, the annotation parameter value is case sensitive, and should exactly match the value of the modelAttribute you declared in userForm.jsp.

Resources