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

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}"

Related

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">

Can't get values submitted using thymeleaf

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

java.lang.IllegalArgumentException: id to load is required for loading

This is my updateUser controller method
#RequestMapping(value = {"/edit-user-{id}"}, method = RequestMethod.POST)
public String updateUser(#Valid User userForm, BindingResult bindingResult, ModelMap model, #PathVariable Long id) {
model.addAttribute("edit", true);
model.addAttribute("success", "User " + userForm.getFirstName() + " " + userForm.getLastName() + " updated successfully");
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "forward:/registration";
}
userService.updateUser(userForm);
model.addAttribute("userForm", userForm);
return "registrationSuccess";
}
this one is my addDocuments method
#RequestMapping(value = {"/add-document-{id}"}, method = RequestMethod.GET)
public String addDocuments(#PathVariable Long id, ModelMap model) {
User user = userService.findById(id);
try {
if (user.getUsername() != null && !user.getUsername().equals(context.getUserPrincipal().getName())) {
return "login";
}
} catch (Exception ex) {
throw new DocumentNotFoundException("No document found with that id or userName");
}
model.addAttribute("user", user);
FileBucket fileModel = new FileBucket();
model.addAttribute("fileBucket", fileModel);
List<Catalog> documents = catalogService.findAllByUserId(id);
model.addAttribute("documents", documents);
return "manageDocuments";
}
when there is binding result error in updateUser method, it enters the "registration.jsp"
and at that time when I press add document button, it throws this kind of exception
nested exception is java.lang.IllegalArgumentException: id to load is required for loading.
this is registration jsp
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="comment" content="">
<meta name="author" content="">
<title>Create an account</title>
<link href="${contextPath}/resources/css/bootstrap.min.css" rel="stylesheet">
<link href="${contextPath}/resources/css/common.css" rel="stylesheet">
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
</head>
<body>
<div class="container">
<form id="logoutForm" method="POST" action="${contextPath}/logout">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<form:form method="POST" modelAttribute="userForm" class="form-signin">
<c:choose>
<c:when test="${edit}">
<h2 class="form-signin-heading"><spring:message code= "account.edit.label"/></h2>
</c:when>
<c:otherwise>
<h2 class="form-signin-heading"><spring:message code= "account.create.label"/></h2>
</c:otherwise>
</c:choose>
<c:if test="${!edit}">
<spring:bind path="username">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="username" class="form-control" placeholder="Username"
autofocus="true"></form:input>
<form:errors path="username"></form:errors>
</div>
</spring:bind>
</c:if>
<spring:bind path="firstName">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="firstName" class="form-control" placeholder="First name"
autofocus="true"></form:input>
<form:errors path="firstName"></form:errors>
</div>
</spring:bind>
<spring:bind path="lastName">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="lastName" class="form-control" placeholder="Last name"
autofocus="true"></form:input>
<form:errors path="lastName"></form:errors>
</div>
</spring:bind>
<spring:bind path="email">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="email" class="form-control" placeholder="Email"
autofocus="true"></form:input>
<form:errors path="email"></form:errors>
</div>
</spring:bind>
<spring:bind path="skypeID">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="text" path="skypeID" class="form-control" placeholder="Skype ID"
autofocus="true"></form:input>
<form:errors path="skypeID"></form:errors>
</div>
</spring:bind>
<spring:bind path="password">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="password" path="password" class="form-control" placeholder="Password"></form:input>
<form:errors path="password"></form:errors>
</div>
</spring:bind>
<spring:bind path="passwordConfirm">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input type="password" path="passwordConfirm" class="form-control"
placeholder="Confirm your password"></form:input>
<form:errors path="passwordConfirm"></form:errors>
</div>
</spring:bind>
<c:if test="${edit}">
<span class="well pull-left">
<spring:message code= "button.upload.text"/>
</span>
</c:if>
<button class="btn btn-lg btn-primary btn-block" type="submit"><spring:message code= "button.submit.label"/></button>
<h3><a onclick="document.forms['logoutForm'].submit()"><spring:message code= "button.logout.label"/></a></h3>
</form:form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="${contextPath}/resources/js/bootstrap.min.js"></script>
</body>
</html>
please help me find out how to redirect or forward.

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