html form handling in thymeleaf and spring boot - java

I am new to springboot and thymeleaf and I'm trying to understand the form handling methods that interact with the code. Below you will find my html documents linked to a Users class. I am trying to change them to link to a customer class amongst other things, but anytime I change the th:object=${users} to match the new entity 'customerentity' it gives me the error below. What more do I have to do to get the bean(?) to register my new attribute? Any help or links to other answers is greatly appreciated.
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'customerentity' available as request attribute
Here is my entity class
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.springframework.lang.NonNull;
#Entity
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NonNull
private String name;
#NonNull
private String email;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// standard constructors / setters / getters / toString
}
The controller class
#Controller
public class UserController {
//set up a UserRepositoty variable
#Autowired
private UserRepository userRepository;
//create an UserRepository instance - instantiation (new) is done by Spring
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
//Mapping for the /index URL when initiated through Tomcat
#RequestMapping({"/index"})
public String showUserList(Model model) {
model.addAttribute("customers", userRepository.findAll());
return "index";
}
//Mapping for the /signup URL - calls the add-user HTML, to add a user
#RequestMapping({"/signup"})
public String showSignUpForm(Users user) {
return "add-user";
}
//Mapping for the /signup URL - to add a user
#RequestMapping({"/adduser"})
public String addUser(#Validated Users users, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-user";
}
userRepository.save(users);
return "redirect:/index";
}
//Mapping for the /edit/user URL to edit a user
#GetMapping("/edit/{id}")
public String showUpdateForm(#PathVariable("id") long id, Model model) {
Users user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
model.addAttribute("customer", user);
return "update-user";
}
//Mapping for the /update/id URL to update a user
#PostMapping("/update/{id}")
public String updateUser(#PathVariable("id") long id, #Validated Users user,
BindingResult result, Model model) {
if (result.hasErrors()) {
user.setId(id);
return "update-user";
}
userRepository.save(user);
return "redirect:/index";
}
//Mapping for the /delete/id URL to delete a user
#GetMapping("/delete/{id}")
public String deleteUser(#PathVariable("id") long id, Model model) {
Users user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
userRepository.delete(user);
return "redirect:/index";
}
}
The html documents
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Add User</title>
</head>
<body>
<form action="#" th:action="#{/adduser}" th:object="${users}" method="post">
<label for="name">Name</label>
<input type="text" th:field="*{name}" id="name" placeholder="Name">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
<label for="email">Email</label>
<input type="text" th:field="*{email}" id="email" placeholder="Email">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
<input type="submit" value="Add User">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Add User</title>
</head>
<body>
<div th:switch="${users}">
<h2 th:case="null">No users yet!</h2>
<div th:case="*">
<h2>Users</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
<td><a th:href="#{/edit/{id}(id=${user.id})}">Edit</a></td>
<td><a th:href="#{/delete/{id}(id=${user.id})}">Delete</a></td>
</tr>
</tbody>
</table>
</div>
<p>Add a new user</p>
</div>
</body>
</html>

Related

From controller, data is not transforming to html view page

I am trying send the data through controller to html page but unable data transmission is getting failed. Control is redirecting to the desired page along with labels but form data is not reflecting in the view page.
***HomeController***
package com.example.demo.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.example.demo.domain.User;
#Controller
public class HomeController {
User user = new User();
#RequestMapping("/")
public String home(Model model) {
model.addAttribute("formData", user);
return "index";
}
#RequestMapping(value="/create", method=RequestMethod.POST)
public String processFormData(User user, RedirectAttributes attr) {
attr.addFlashAttribute("user",user);
return "redirect:display";
}
#RequestMapping(value="/display", method=RequestMethod.GET)
public String displayFormData(User user) {
return "result";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title> Home Page </title>
</head>
<body>
<p> Enter Data Below </p>
<form action="/create" method="post" th:object="${formData}">
<p>Full Name:<input type="text" th:feild="${formData.fullName}"/></p>
<p>Age:<input type="text" th:feild="${formData.age}"/></p>
<p>Employed?<input type="checkbox" th:feild="${formData.employed}" th:value="true"/></p>
<p>Gender:</p>
<p>Male<input type="radio" th:feild="${formData.gender}" th:value="Male"/>
Female<input type="radio" th:feild="${formData.gender}" th:value="Female"/></p>
<p><input type="submit" value="Submit"/> <input type="reset" value="Reset"/></p>
</form>
</body>
</html>
result.html
<html xmlns:th="https://thymeleaf.org">
<table>
<tr>
<td><h4>User Name: </h4></td>
<td><h4 th:text="${user.fullName}"></h4></td>
</tr>
<tr>
<td><h4>Age: </h4></td>
<td><h4 th:text="${user.age}"></h4></td>
</tr>
</table>
</html>
The controller class sends and reads a form view. The User data is passed as a parameter to the processForm() handler. Spring tries to fill the bean with the request data. The data is also automatically available for the Thymeleaf result view. The #Controller annotation allows the implementation classes to be autodetected through the classpath scanning.
#Controller is typically used in combination with a #RequestMapping annotation used on request handling methods. I used the #GetMapping and ##PostMapping` as a shortcut to #RequestMapping(method = RequestMethod.POST)
#Controller
public class HomeController {
//This responds to localhost:8080/
#GetMapping("/")
public String sendForm(User user){
return "index";
}
//This responds to localhost:8080/
#PostMapping("/")
public String processForm(User user){
return "result";
}
User Class. This is the User class. It is automatically filled with data from the form request. The attributes must match the form fields. You should be able to see the matching attribute names in the template views below.
public class User {
private String fullName;
private int age;
private String occupation;
public String getFullName() {
return fullName;
}
public void setFullName(String name) {
this.fullName = name;
}
public String getOccupation() {
return occupation;
}
public void setOccupation(String occupation) {
this.occupation = occupation;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
index.html
The th:object refers to the user form bean. This is not a class name, but a Spring bean name; therefore it is in lowercase. With the *{} syntax, we refer to the defined object. In this case its the user object. I noticed that you misspelled th:field, this can also create bugs.
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title></title>
</head>
<body>
<p> Enter Data Below </p>
<form th:action="#{/}" th:object="${user}" method="post">
<p>Full Name:<input type="text" th:field="*{fullName}" id="fullName" name="fullname" autofocus="autofocus"></p>
<p>Age:<input type="number" th:field="*{age}" id="age" name="age" autofocus="autofocus" /></p>
<p><input type="submit" value="Submit"/> <input type="reset" value="Reset"/></p>
</form>
</body>
</html>
result.html
We identify the form attributes with the ${} syntax.
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title></title>
</head>
<body>
<table>
<tr>
<td><h4>User Name: </h4></td>
<td><h4 th:text="${user.fullName}"></h4></td>
</tr>
<tr>
<td><h4>Age: </h4></td>
<td><h4 th:text="${user.age}"></h4></td>
</tr>
</table>
</body>
</html>

can't view records stored in DB in a web page

I'm referring to this guide (http://jvmhub.com/2015/08/09/spring-boot-with-thymeleaf-tutorial-part-3-spring-data-jpa/), the only difference is that i unified the classes PostEntity and Post assuming the name PostEntity.
When i try to store data in db through a form the applications works but it can't allow me to view stored data in a webpage as showed in the guide linked above.
The web page result.html is displayed as
"Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Jul 05 14:25:42 CEST 2018
There was an unexpected error (type=Internal Server Error, status=500).
Exception evaluating SpringEL expression: "PostEntity.title" (template: "result" - line 11, col 9)"
and the console shows the exception:
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'title' cannot be found on null
It is throwed even with the other attributes (id and content) according to the order they are disposed in result.html.
If i try to print the content of records variable to the console it shows that it is not null so i can't figure out why there is this exception.
Controller:
#Controller
public class Home {
#Autowired private PostRepository postRepository;
#RequestMapping(value="/", method=RequestMethod.GET)
public String index(Model model) {
model.addAttribute("post", new PostEntity());
return "index";
}
#RequestMapping(value = "/", method = RequestMethod.POST)
public String addNewPost( PostEntity post, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "index";
}
postRepository.save(post);
List<PostEntity> records = (List<PostEntity>) postRepository.findAll();
model.addAttribute("posts", records);
return "redirect:result";
}
#RequestMapping(value = "/result", method = RequestMethod.GET)
public String showAllPosts(Model model) {
List<PostEntity> records = (List<PostEntity>) postRepository.findAll();
for (PostEntity record : records) {
System.out.println(record);
}
model.addAttribute("posts", records);
return "result";
}
}
Model class:
#Entity
public class PostEntity {
public PostEntity() {}
public PostEntity(String title, String content) {
this.title = title;
this.content = content;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int id;
public String title;
public String content;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
index:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot and Thymeleaf example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>Spring Boot and Thymeleaf, part 2 - forms</h3>
<form action="#" th:action="#{/}" th:object="${post}" method="post">
<table>
<tr>
<td>Title:</td>
<td><input type="text" th:field="*{title}" /></td>
<td th:if="${#fields.hasErrors('title')}" th:errors="*{title}">Title error message</td>
</tr>
<tr>
<td>Content:</td>
<td><input type="text" th:field="*{content}" /></td>
<td th:if="${#fields.hasErrors('content')}" th:errors="*{content}">Content error message</td>
</tr>
<tr>
<td><button type="submit">Submit post</button></td>
</tr>
</table>
</form>
</body>
</html>
result
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot and Thymeleaf example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h3>Spring Boot and Thymeleaf, part 3 - SPRING DATA JPA</h3>
<p th:each="PostEntity : ${posts}">
<h4>Title:</h4>
<div th:text="${PostEntity.title}"/></div>
<h4>ID:</h4>
<div th:text="${PostEntity.id}"/></div>
<h4>Content:</h4>
<div th:text="${PostEntity.content}"/></div>
<div>---------------------------------------------------------</div>
</p>
</body>
</html>
Any suggestions?
You are doing this redirect-thing. When doing this your objects added to the model doesn't reach the further process. I remember running into similar trouble.

Accessing Object in View with Thymeleaf

I have an customer object whose fields I'm trying to access in my view with Thymeleaf. I've used the usual syntax i.e:
<p th:text="${customer.name}"></p>
however, this does not work, it does work when I use the get() method i.e:
<p th:text="${customer.get.name}"></p>
Any idea why that is happening? I'm just getting started with Thymeleaf, so I apologize in advance if this is a dumb question.
Here's my Model:
#Id
#GeneratedValue
private int id;
#NotNull
#Size(min = 2, message="Company name length must be at least 1 character long.")
private String name;
public Customer() {}
public Customer(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
And the Controller:
#RequestMapping("")
public String index(Model model) {
model.addAttribute("title", "Home");
model.addAttribute("customers", customerDao.findAllByOrderByNameAsc());
return "index";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String processFetch(#ModelAttribute Customer customer, Model model) {
model.addAttribute("title", "Home");
model.addAttribute("customers", customerDao.findAllByOrderByNameAsc());
model.addAttribute("c", customerDao.findById(customer.getId()));
return "index";
}
and the View:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments::head"></head>
<body>
<nav th:replace="fragments::nav"></nav>
<div class="container">
<h1 class="title" th:text="${title}"></h1>
</div>
<div style="text-align: center">
<form method="post" th:object="${customers}" style="display: block;margin: 0 auto;width:300px;margin-top:5%">
<select class="form-control" name="customer">
<option style="text-align:center" th:each="customer:${customers}" th:value="${customer.id}" th:text="${customer.name}"></option>
</select>
<input class="button" style="display:block;margin:0 auto;margin-top:30px" type="submit" value="Fetch" />
</form>
</div>
<div>
<h1 th:text="${c.get().name}"></h1>
</div>
</body>
</html>
Here's my Repository class:
public interface CustomerDao extends CrudRepository<Customer, Integer> {
public Iterable<Customer> findAllByOrderByNameAsc();
}
The error I try to submit the form is:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
I'm not sure why it cannot find property 'name'. It should be part of the object.
I appreciate any insight into this!

Failed to convert property value of type java.lang.String to required type long for property phone; nested exce

I am trying to built my first Spring mvc application And working on Spring Mvc Form Validation.I am trying to check for empty field. But when to validate the 'long' type variable with #NotNull annotation it give me the above error.
I don't know how to solve it.
Here is My Student Bean
public class Student {
#NotNull
#Pattern(regexp="[A-Za-z]+")
private String name;
#Size(min=2, max=10)
private String father;
private String cnic;
#NotBlank
private String email;
#NotNull
private long phone;
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCnic() {
return cnic;
}
public void setCnic(String cnic) {
this.cnic = cnic;
}
public String getFather() {
return father;
}
public void setFather(String father) {
this.father = father;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
And my studentmessage.properties file
Pattern.student1.name=The should not contain any Digits
Size.student1.father=please give the {0} between {2} and {1} characters
NotBlank.student1.email=please the email are requried
NotNull.student1.phone=sPlease provide integer data
Controller Class
#Controller
#RequestMapping(value="/student")
public class StudentController {
#RequestMapping(value="/Student",method=RequestMethod.GET)
public String std(Model m){
m.addAttribute("message", "Welcome To Registration ");
return "studentreg";
}
public ModelAndView insert(#Valid #ModelAttribute("student1") Student student1,BindingResult result) //ModelAttribute is used to directly connect the form data to the bean class
{
if(result.hasErrors()){
ModelAndView model=new ModelAndView("studentreg");
return model;
}
ModelAndView mo=new ModelAndView("success");
mo.addObject("message","user detail");
mo.addObject("stu", student1);
return mo;
}
}
Jsp file is
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#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>Insert title here</title>
</head>
<body>
<h2 align="center">${ message}</h2>
<form:errors path="student1.phone" style="color:red"/><br>
<form:form name="form" method="post" action="stu" >
<div align="center">
<table>
${ error}
<tr>
<td>Name :</td><td><input type="text" name="name" placeholder="EnterName"></td>
</tr>
<tr>
<td>Father Name</td>
<td><input type="text" name="father" placeholder="EnterFatherName"/></td>
</tr>
<tr>
<td>CNIC</td>
<td><input type="text" name="cnic" placeholder="Enter CNIC"/></td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" name="email" placeholder="Enter Email"/></td>
</tr>
<tr>
<td>Phone:</td>
<td><input type="text" name="phone" placeholder="Enter Phone"/></td>
<form:errors path="phone"/>
</tr>
<tr>
<td><input type="submit" name="submite" value="Send"/></td>
</tr>
</table>
</table>
</table>
</div>
</table>
</form:form>
</body>
</html>
Try to use Long instead of long.
Because long can never be null it is not primitive type.
So you should use Long.

Spring 4 and thymeleaf form validatation

Can anyone give sample Java code for validating the HTML form (ex: form attributes not null, minimum and maximum size) using via Spring MVC and with thymeleaf-spring4 libraries?
The simplest, you annotate your dao object (in this case user), with the constraints you need:
#Entity
public class User
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NotNull
private String login;
#Size(min=2, max=30)
private String firstName;
#Min(18)
private int age;
}
These annotation are from javax.validation.constraints.
After this you need to modify your controller, you need to clarify your controller that the object must be #Valid:
#RequestMapping(method=RequestMethod.POST)
public String registerUser(#Valid final User user, final BindingResult bindingResult)
{
if (bindingResult.hasErrors()) {
return "form";
}
// Your code
return "redirect:/userList";
}
The errors are stored in the BindingResult.
Finally show the errors:
<span th:if="${#fields.hasErrors('login')}" th:errors="*{login}"></span>
Edit:
Return ModelAndView
#RequestMapping(method=RequestMethod.POST)
public ModelAndView registerUser(#Valid final User user, final BindingResult bindingResult)
{
if (bindingResult.hasErrors()) {
ModelAndView mav = new ModelAndView("form");
mav.addObject(bindingResult);
return mav;
}
}
These are latest maven dependencies for java validation API
1.dependency
groupId javax.validation
artifactId validation-api
version 1.1.0.Final
2.dependency
groupId org.hibernate
artifactId hibernate-validator
version 5.0.1.Final
Take a look at this:
First, comes the Object...
public class PruebaFormCommand {
#NotEmpty
#Size(min = 3, max = 50)
private String textoPrueba;
public String getTextoPrueba() {
return textoPrueba;
}
public void setTextoPrueba(String textoPrueba) {
this.textoPrueba = textoPrueba;
}
}
Then, the Controller:
#Controller
public class PruebaFormController {
#RequestMapping("/pruebaform")
public String pruebaForm(Model model){
model.addAttribute("pruebaFormCommand", new PruebaFormCommand());
return "pruebaform";
}
#RequestMapping(value = "/dopruebaform", method = RequestMethod.POST)
public String doPruebaForm(#Valid PruebaFormCommand pruebaFormCommand, BindingResult bindingResult){
if (bindingResult.hasErrors()) {
return "pruebaform";
}
return "pruebaformcomplete";
}
}
Then, the HTML:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<link href="../static/css/bootstrap-3.3.4-dist/css/bootstrap.min.css" rel="stylesheet" media="screen"
th:href="#{/css/bootstrap-3.3.4-dist/css/bootstrap.min.css}"/>
<script src="../static/js/jquery-2.1.4.min.js"
th:src="#{/js/jquery-2.1.4.min.js}"></script>
<link th:href="#{/css/custom.css}" rel="stylesheet" media="screen"/>
<title>Checkout</title>
</head>
<body>
<div class="container">
<h2>PRUEBA Form</h2>
<form class="form-horizontal" th:object="${pruebaFormCommand}" th:action="#{/dopruebaform}" method="post">
<div th:if="${#fields.hasErrors('*')}" class="alert alert-danger">
<p th:text="#{pruebaFormCommand.hasErrors}">Error Message</p>
</div>
<div class="form-group" th:class="${#fields.hasErrors('textoPrueba')} ? 'form-group has-error' : 'form-group'">
<label class="col-sm-2 control-label">Meteme algo payo:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{textoPrueba}" th:errorclass="has-error"/>
<span class="help-block" th:if="${#fields.hasErrors('textoPrueba')}">
<ul>
<li th:each="err : ${#fields.errors('textoPrueba')}" th:text="${err}" />
</ul>
</span>
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>
</body>
</html>
Finally, include your message.properties:
pruebaFormCommand.hasErrors=Porfa corrige los errores:
NotEmpty.pruebaFormCommand.textoPrueba={0} caracteres mínimo....
Size.pruebaFormCommand.textoPrueba={0} debe tener entre {2} y {1} caracteres

Categories