Can't get values submitted using thymeleaf - java

I am new with thymeleaf and I am having a doubt about how to retrieve a field from html (using Thymeleaf) to Java (Spring Boot). Follow the code and the error that I am having:
HTML (part with issue)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1.0" />
<title>Entity Migration</title>
<!-- CSS -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
<link href="css/style.css" type="text/css" rel="stylesheet"
media="screen,projection" />
<link href="css/materialize.css" type="text/css" rel="stylesheet"
media="screen,projection" />
</head>
<body>
<nav class="light-blue lighten-1" role="navigation">
<div class="nav-wrapper container">
<a id="logo-container" href="#" class="brand-logo">Entity
Migration</a>
<ul class="right hide-on-med-and-down">
<li>Logout</li>
</ul>
<ul id="nav-mobile" class="side-nav">
<li>Entity Migration</li>
</ul>
<a href="#" data-activates="nav-mobile" class="button-collapse"><i
class="material-icons">Logout</i></a>
</div>
</nav>
<div class="section no-pad-bot" id="index-banner">
<div class="container">
<br> <br>
<div class="row center">
<h5 class="header col s12 light">Fill the form below to
generate your XML:</h5>
</div>
<br> <br>
</div>
</div>
<form class="col s12" action="#" th:action="#{/prepareData}" th:object="${entity}" method="post">
<div class="row">
<div class="input-field col s4">
<input type="number" id="release" name="release" placeholder="Release"
class="validate" th:value="*{release}"/>
</div>
<div class="input-field col s4">
<input placeholder="Version" id="version" name="version" type="number"
class="validate" th:value="*{version}"/>
</div>
</div>
<input type="submit" value="Generate XML" id="generate"
class="btn-large waves-effect waves-light orange" />
</div>
</form>
<!-- Scripts-->
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="js/init.js"></script>
<script src="js/materialize.js"></script>
<script>
$(document).ready(function() {
$('select').material_select();
});
</script>
</body>
</html>
Java (Spring Boot Controller)
#PostMapping(value = "/prepareData")
public String prepareData(#ModelAttribute(value="entity") EntityMigration entity) {
TemplatePrepare tP = new TemplatePrepare();
tP.prepareMainTemplate(entity);
return "results";
EntityMigration (Java Model)
public class EntityMigration {
private String release;
private String version;
public String getRelease() {
return release;
}
public void setRelease(String release) {
this.release = release;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
Error
2017-11-16 14:01:02.445 ERROR 26932 --- [nio-8080-exec-1] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8080-exec-1] Exception processing template "mainForm": An error happened during template parsing (template: "class path resource [templates/mainForm.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/mainForm.html]")
(...)
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "release" (template: "mainForm" - line 55, col 23)
(...)
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'release' cannot be found on null
(...)
What am I doing wrong?
Thank you.

Parsing html exception was caused by forgetting to close input tags. Please replace:
<input type="number" id="release" placeholder="Release" class="validate" th:value="*{release}">
<input placeholder="Version" id="version" type="number" class="validate">
with:
<input type="number" id="release" placeholder="Release" class="validate" th:value="*{release}"/>
<input placeholder="Version" id="version" type="number" class="validate"/>
Latter error:
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'release' cannot be found on null
is caused by trying to access 'release' on 'entity' -> entity is null so Thymeleaf can't render it.
You must addAttribute 'entity' to model in order to render it.
In order to avoid SpelEvaluationException you can check for null in controller:
if (entityManager!= null) {
model.addAttribute("entity", entityManager);
} else {
model.addAttribute("entity", new EntityManager());
}

you forgot to use the name attribute in the input, and to close you input, so replace:
<input placeholder="Version" id="version" type="number" class="validate">
<input type="number" id="release" placeholder="Release" class="validate" th:value="*{release}">
with:
<input placeholder="Version" id="version" name="version" type="number" class="validate" />
<input type="number" id="release" name="release" placeholder="Release" class="validate" th:value="*{release}" />
or you can use the

Related

Neither BindingResult nor plain target object for bean name

I've been tinkering with Thymeleaf recently a little bit and I'm trying to setup a basic registration form. I have set up my #GetMapping and #Postmapping controller handlers.
Controller:
#GetMapping("/registration")
public String userResponseEntity(Model model) {
UserModel userModel = new UserModel();
model.addAttribute("userModel", userModel);
return "registration";
}
#PostMapping("/registration")
public String userRegistration(#Valid #ModelAttribute("userModel") UserModel user, BindingResult result){
UserModel userToSubmit = new UserModel();
userToSubmit.setUsername(user.getUsername());
userToSubmit.setFirstName(user.getFirstName());
userToSubmit.setLastName(user.getLastName());
try {
User userReturned = userService.saveUser(userToSubmit).orElseThrow(
() -> new UserException(HttpStatus.BAD_REQUEST, "Unable to register user with given inputs"));
}catch (UserException e){
if(result.hasErrors()) {
logger.error("Could not save the given user to the database");
return "registration?error=true";
}
}
logger.info(String.format("User: %s has been registered successfully", userToSubmit.getUsername()));
return "registration?user-created=true";
}
The error I have been getting occurs when I click on a button that is not shown in the controller to minimizing purposes, but has the following href from a button located at /login
<p>Not a member? <a th:href="#{/registration}" >Register</a></p>
After I click on that I am not even redirected to /registration, but instead prompted with the following error:
2022-12-21T19:07:11.241-06:00 ERROR 2109 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring6.processor.SpringInputGeneralFieldTagProcessor' (template: "registration" - line 22, col 94)] with root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'userDTO' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153) ~[spring-webmvc-6.0.2.jar:6.0.2]
The Thymeleaf template:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"/>
</head>
<body>
<div class="container-fluid text-left">
<div class="row justify-content-md-center mt-3">
<div class="col-4">
<h3 class="fw-normal mb-3 pb-3 text-center" style="letter-spacing: 1px;">Register Account</h3>
<div th:if="${param.error}">//fields has errors
<p class="text-danger">[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</p>
</div>
<form th:action="#{/registration}" method="post" th:object="${userModel}">
<div class="form-group">
<label for="exampleInputEmail1" class="text-left">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" th:field="*{username}" aria-describedby="emailHelp" placeholder="Enter email">
</div>
<div class="form-group">
<label for="InputPassword" class="text-left">Password</label>
<input type="password" class="form-control" th:field="*{password}" id="InputPassword" placeholder="Password">
<label for="ReenterPassword" class="text-left">Re-enter Password</label>
<input type="password" class="form-control" th:field="*{password}" id="ReenterPassword" placeholder="Enter password again">
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">Check me out</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>

Edit data in the database

I want to edit exist data from database via html-form with field. But I can not create a right controller for it, because this code just created a new book. Old data was not changed.
Controller
#GetMapping("/bookUpdate/{id}")
public String bookListUpdate(#PathVariable (value = "id") Integer id, Model model, #Valid
BookDto book) {
model.addAttribute("book", service.findById(id));
return "views/bookUpdate";
}
#PostMapping("/edit")
public String editBook(#Valid Book book, #PathVariable (value = "id") Integer id) {
Book newBook = service.findById(id);
newBook.setDescription(book.getDescription());
newBook.setTopic(book.getTopic());
newBook.setLink(book.getLink());
service.saveBook(newBook);
return "views/index";
}
BookUpdate
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="~{fragments/main_layout}">
<head>
<title>Book Form</title>
</head>
<body>
<div layout:fragment="content" class="container mySpace">
<form th:action="#{/edit}" th:object="${book}" method="post">
<div class="form-group">
<label for="topic" class="form-control-label">Topic</label> <input
type="text" class="form-control" th:field="*{topic}" id="topic" />
</div>
<div class="form-group">
<label for="description" class="form-control-label">Description</label>
<textarea class="form-control" th:field="*{description}"
id="description" style="height: 95px"></textarea>
</div>
<div class="form-group">
<label for="link" class="form-control-label">Link</label><a href=""> <input
type="text" class="form-control" th:field="*{link}" id="link" />
</div>
<input type="submit" value="Submit" class="btn btn-primary" />
</form>
</div>
</body>
</html>
Your #PostMapping is missing the path variable:
#PostMapping("/edit")
Do something like:
#PostMapping("/edit/{id}")
On a side note, you can make your URLs a bit nicer, by using something like #GetMapping("/books/{id}") and #PostMapping("/books/{id}").

Can not edit data from database via thymeleaf and spring

I want to edit data from database via form "bookUpdate.html", that I can open from page "bookList.html" with the list of all rows from the table. I created a controller and form, that redirect me to the page with filled fields, that contain right data according the value "id", where object = "book". Button "Edit" redirect me to the page "/bookUpdate/1?", it is right. But when I try to confirm a new information via button on this page, this action redirect me to "bookUpdate.html" with an error 404, and new data were not saved in database. I can not find a mistake in this case.
bookUpdate.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="~{fragments/main_layout}">
<head>
<title>Book Form</title>
</head>
<body>
<div layout:fragment="content" class="container mySpace">
<form th:action="#{/bookUpdate}" th:object="${book}" method="post">
<div class="form-group">
<label for="topic" class="form-control-label">Topic</label> <input
type="text" class="form-control" th:value="${book.topic}"
id="topic" />
</div>
<div class="form-group">
<label for="description" class="form-control-label">Description</label>
<textarea class="form-control" th:value="${book.description}"
id="description" style="height: 95px"></textarea>
</div>
<div class="form-group">
<label for="link" class="form-control-label">Link</label> <input
type="text" class="form-control" th:value="${book.link}" id="link" />
</div>
<input type="submit" value="Submit" class="btn btn-primary" />
</form>
</div>
</body>
</html>
Contoller
#Controller
public class BookUpdateController {
#Autowired
private BookService service;
#PostMapping("/bookUpdate/{id}")
public String editBook(#Valid BookDto book, #PathVariable (value = "id") Integer id, Model
model) {
Book oldBook = service.findById(id);
oldBook.setDescription(book.getDescription());
oldBook.setTopic(book.getTopic());
oldBook.setLink(book.getLink());
service.saveBook(oldBook);
model.addAttribute("book", new BookDto());
return "redirect:/bookList";
}
}
#GetMapping("/bookUpdate/{id}")
public String bookListUpdate(#PathVariable (value = "id") Integer id, Model model) {
model.addAttribute("book", service.findById(id));
return "views/bookUpdate";
}
bookList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="~{fragments/main_layout}">
<head>
<title>Books</title>
</head>
<body>
<div layout:fragment="content" class="container mySpace">
<form action="/bookList" class="form-inline">
<div class="form-group mb-2" >
<input type="text" class="form-control" name="name"
placeholder="Search book" /> <input type="submit" value="Search"
class="btn btn-primary" />
</div>
</form>
<div class="card">
<div class="card card-body">
<ul th:each="books:${book}" style="list-style: none; padding-left: 10px;">
<li><b>Topic:</b> <span th:text="${books.topic}"></span></li>
<li><b>Description:</b><p th:text="${books.description}"></p></li>
<li><b>Link:</b> <span th:text="${books.link}"></span></li>
<br>
<form class="form-inline my-2 my-lg-0"
th:action="#{'/bookUpdate/'+${books.id}}" th:object="${books}" method="get">
<input class="form-control mr-sm-2" type="hidden" />
<button class="btn btn-secondary my-2 my-sm-0" type="submit"
>Edit</button>
</form>
<hr>
</ul>
</div>
</div>
</div>
</body>
</html>
In your bookUpdate.html file, the action property is not set correctly. Your form after posting send information to #{/bookUpdate} but in related controller, defined PostMapping required #PostMapping("/bookUpdate/{id}") and they are mismach.
Change your form action property to :
<form th:action="#{'/bookUpdate/'+${book.id}}" th:object="${book}" method="post">

Java. Thymeleaf. After CRUD operation all .CSS styles on page disappearing

A have simple CRUD web application. And I want to bind UI and backend with thymeleaf. After I create some data and get server response - all styles are disappearing. I'm new to thymeleaf, CSS and HTML. Can someone help me to figure out where is the problem?
Before and after:
Save operation method:
#PostMapping("/user/save")
public ModelAndView save(#ModelAttribute("userDTO") #Valid UserDTO userDTO,
BindingResult bindingResult, WebRequest request, Errors errors) {
User registered = new User();
if (!bindingResult.hasErrors()) {
registered = createUserAccount(userDTO, bindingResult);
}
if (registered == null) {
bindingResult.rejectValue("email", "message.regError");
}
if (bindingResult.hasErrors()) {
bindingResult.getAllErrors().forEach(error -> log.error(error.toString()));
return new ModelAndView("authorization/registration", "error", bindingResult.getAllErrors());
} else {
return new ModelAndView("users", "user", userDTO);
}
}
registration.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>User Registration</title>
<div th:replace="fragments/css_fragments :: css_background_layer"></div>
</head>
<body>
<div style="text-align:center">
<div th:replace="fragments/menu_fragments :: header_menu"></div>
</div>
<div style="margin: 0 auto; width: 20%; padding-top: 18%;">
<div class="registration-form">
<!--/*#thymesVar id="userDTO" type="com.socnetw.socnetw.model.UserDTO"*/-->
<form id="form" method="post" action="/user/save" th:object="${userDTO}">
<label>
<input name="username" placeholder="Username" required="required" th:field="*{username}"
type="text">
</label>
<ul>
<li th:each="err : ${#fields.errors('username')}" th:text="${err}"></li>
</ul>
<label>
<input name="realName" placeholder="Real Name"
type="text" th:field="*{realName}">
</label>
<ul>
<li th:each="err : ${#fields.errors('realName')}" th:text="${err}"></li>
</ul>
<span></span><br>
<label>
<input name="email" placeholder="Email" required="required" th:field="*{email}"
type="email">
</label>
<ul>
<li th:each="err : ${#fields.errors('email')}" th:text="${err}"></li>
</ul>
<label>
<input name="phoneNumber" placeholder="Phone Number" required="required" th:field="*{phoneNumber}"
type="tel">
</label>
<ul>
<li th:each="err : ${#fields.errors('phoneNumber')}" th:text="${err}"></li>
</ul>
<span></span><br>
<label>
<input name="password" placeholder="Password" th:field="*{password}"
required="required" type="password">
</label>
<ul>
<li th:each="err : ${#fields.errors('password')}" th:text="${err}"></li>
</ul>
<label>
<input name="passwordMatcher" placeholder="Repeat password" th:field="*{matchingPassword}"
required="required" type="password">
</label>
<ul>
<li th:each="err : ${#fields.errors('matchingPassword')}" th:text="${err}"></li>
</ul>
<span></span><br>
<button type="submit" style="margin-top: 20px">Register</button>
</form>
</div>
</div>
</body>
</html>
css fragment
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<div th:fragment="css_background_layer">
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"
rel="stylesheet"
th:href="#{'https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css'}"
type="text/css">
<link href="css/style.css" rel="stylesheet"
th:href="#{css/style.css}"
type="text/css">
<div class="overlay"></div>
</div>
</html>
You need to use an absolute url to your css, rather than a relative one. When you go to /user/save it's looking for /user/save/css/style.css -- which probably doesn't exist.
th:href="#{/css/style.css}"

HTTP Status 405 - Request method 'GET' not supported

I want to add payments to my clients database but when I add the payments I got this error "GET NOT SUPPORTED" I don't know what's the problem. Can you guys help me?
#Controller
public class PaymentsController {
#Autowired
private UsersService usersService;
#Autowired
private PaymentsService paymentsService;
#RequestMapping(value = "/addPayments", method = RequestMethod.POST)
public String addPayments(HttpServletRequest request, ModelMap map) {
String user = request.getParameter("userId"); // this is the identifier for the user of this payment
String transactName = request.getParameter("transactName");
String paid = request.getParameter("paid");
String unpaid = request.getParameter("unpaid");
String balance = request.getParameter("balance");
String total = request.getParameter("total");
//.... get all other attributes you've passed from the form through request.getParameter("");
//next, check whether or not a user with the userId from the screen exists in the db
Users userObject = usersService.getUsers(user);
//.getUsersByUserId(user);
if (userObject != null) {
// this means that we have a valid user to insert the payment to
UsersPayments payment = new UsersPayments();
payment.setUsers(userObject);
payment.setTransactName(transactName);
payment.setPaid(paid);
payment.setUnpaid(unpaid);
payment.setBalance(balance);
payment.setTotal(total);
//.... set the other properties of UsersPayment object
paymentsService.addPayments(payment);
}
else {
// you have an error right here
}
map.put("paymentsList", paymentsService.getAllPayments());
return "payments";
}
}
payments.jsp:
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# include file="/WEB-INF/jsp/includes.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link href="<c:url value="/resources/css/design.css" />" rel="stylesheet">
<link href="<c:url value="/resources/css/customized.css" />" rel="stylesheet">
<link href="<c:url value="/resources/css/bootstrap.css" />" rel="stylesheet">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Canadian Immigration Consultancy</title>
</head>
<body>
<div id="wrapper">
<div id="logo">
<img src="<c:url value="/resources/images/logo4.png" />" height="200px" width="230px"/>
<img src="<c:url value="/resources/images/header06.jpg" />" height="200px" width="765px"/>
</div>
<div class="red">
<div align="center" id="slatenav">
<ul>
<li>Home</li>
<li>View All</li>
<li>Reports</li>
<li>Add Leads</li>
<li><spring:message code="user.logout"/></li>
</ul>
</div>
</div>
<div id="balance" >
<form action="addPayments" method="POST">
<div class="well well-sm box16">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Payments</h3>
</div>
<div class="panel-body">
<div class="form-group">
<br><div class="col-sm-2 control-label">Transaction Name</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="transactName" autofocus />
</div>
</div>
<div class="form-group">
<br><div class="col-sm-2 control-label">Amount Paid</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="paid" />
</div>
</div>
<div class="form-group">
<br><div class="col-sm-2 control-label">Unpaid</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="unpaid" />
</div>
</div>
<div class="form-group">
<br><div class="col-sm-2 control-label">Total Balance</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="balance" />
</div>
</div>
<div class="form-group">
<br><div class="col-sm-2 control-label">Total Amount</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="total" />
</div>
</div>
<div class="save">
<input type="submit" class="btn btn-success" value="Save" />
</div>
</form>
</div>
</div>
</div>
</body>
</html>
You only seem to have one handler mapping, and it's POST. Add another handler mapping for the same url path with GET. Consider the "POST Redirect GET" pattern as well.

Categories

Resources