How pass field from html that is not part of pojo? - spring-boot

In my spring-boot app:
POJO:
#Entity
#Table(name = "usr") // PostgreSQL not work with table "user"
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NotNull
private String username;
#NotNull
private String password;
#NotNull
private boolean active;
#NotNull
#ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
#CollectionTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"))
#Enumerated(EnumType.STRING)
private Set<Role> roles;
here Controller:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import ru.otus.software_architect.eshop.repo.UserRepository;
import java.util.Collections;
#Controller
public class RegistrationController {
#Autowired
private UserRepository userRepository;
#Value("${spring.application.name}")
private String appName;
private static Logger logger = LogManager.getLogger(RegistrationController.class);
#GetMapping("/registration.html")
public String registration(Model model) {
logger.info("open_registration.html");
model.addAttribute("appName", appName);
return "registration.html";
}
#PostMapping("/registration.html")
public String registartionNewUser(User user, Model model) {
logger.info("user = " + user);
if (user.getUsername().trim().isEmpty()
|| user.getPassword().trim().isEmpty()
) {
model.addAttribute("registrationError", "Аll fields are required!");
return "registration.html";
}
user.setActive(true);
user.setRoles(Collections.singleton(Role.USER));
User userFromDb = userRepository.findByUsername(user.getUsername());
if (userFromDb != null) {
model.addAttribute("registrationError", "User already exist!");
return "registration.html";
}
userRepository.save(user);
return "redirect:/login.html";
}
}
here html template:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${appName}">Template title</title>
<link th:href="#{/public/style.css}" rel="stylesheet"/>
</head>
<body>
<div id="container">
<h2 align="center">Registration new user</h2>
<form th:action="#{/registration.html}" method="post">
<label for="username">Username</label>
<input type="text" id="username" name="username" autofocus="autofocus"/>
<label for="password">Password</label>
<input type="password" id="password" name="password"/>
<label for="retypePassword">Retype password</label>
<input type="password" id="retypePassword" name="retypePassword"/>
<input id="submit" type="submit" value="Registration"/>
</form>
<p th:if="${registrationError}" th:text="${registrationError}" class="error"></p>
</div>
</body>
</html>
As you can see I pass POJO User from html and check is username and password was filled.
Nice.
But I also need to check is password and retypePassword are equals.
The problem is that retypePassword is not part of POJO User (no property retypePassword).
How I can pass retypePassword from html to method registartionNewUser to check password and retypePassword ?

have retypePassword as another argument in method registartionNewUser.
public String registartionNewUser(User user, String retypePassword, Model model)

Related

Thymeleaf form returns null values

when I submit the form, the pageBook.id and loggedUser.id values become null (in GetMapping method they have values). Any ideas why?
This is my form:
<div sec:authorize="isAuthenticated()">
<form th:action="#{/} + ${pageBook.id}" th:object="${transaction}" method="post">
<input type="hidden" th:field="${transaction.bookTransaction}" th:value="${pageBook.id}">
<input type="hidden" th:field="${transaction.userTransaction}" th:value="${loggedUser.id}">
<input type="submit" value="Submit!" />
</form>
</div>
My Entity:
#Entity
#Table(name = "transactions")
public class Transaction {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="book_id", nullable=false)
private Book bookTransaction;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="user_id", nullable=false)
private User userTransaction;
... consturctors getters and setters
and my controller (pageBook and loggedUser aren't null):
#GetMapping("/{id}")
public String showBookPage(#AuthenticationPrincipal UserDetails userDetails, #PathVariable("id") Long id, Model model, RedirectAttributes redirectAttributes){
try {
Book pageBook = bookService.getBookById(id);
User loggedUser = (User) userService.loadUserByUsername(userDetails.getUsername());
model.addAttribute("transaction", new Transaction());
model.addAttribute("pageBook", pageBook);
model.addAttribute("loggedUser", loggedUser);
} catch (BookNoFoundException e) {
redirectAttributes.addFlashAttribute("message", e);
}
return "users/users_book_page";
}
#PostMapping("/{id}")
public String newTransaction(#PathVariable("id") Long id, #ModelAttribute("transaction") Transaction transaction){
log.info(transaction.getUserTransaction());
log.info(transaction.getBookTransaction());
transactionService.newTransaction(transaction);
return "redirect:/" + id;
}

Cannot resolve 'name'

Hi all, I'm currently doing a crud app using spring mvc, hibernate and thymeleaf. I am trying to create a new user but the compiler is complaining that it can't recognize the name field, even though I have this field in the User class. What can be the problem?
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>New User</title>
</head>
<body>
<form th:method="POST" th:action="#{/users}" th:object="${user}">
<input type="text" th:field="*{name}" id="name">
</form>
</body>
</html>
User class:
package web.model;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#GenericGenerator(name = "increment", strategy = "increment")
private int id;
#Column(name = "name", nullable = false, length = 50)
private String name;
public User() {}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
}
UserController:
package web.controller;
import jdk.internal.icu.text.NormalizerBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import web.model.User;
import web.service.UserService;
#Controller
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService userService;
#GetMapping
public String listUsers(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "users";
}
#GetMapping("/{id}")
public String show(#PathVariable("id") int id, Model model) {
model.addAttribute("user", userService.getUserById(id));
return "show";
}
#GetMapping("/new")
public String newUser(Model model) {
model.addAttribute("user", new User());
return "new";
}
#PostMapping()
public String create(#ModelAttribute("user") User user) {
userService.add(user);
return "redirect:/users";
}
}
What could be the problem?

Thymeleaf : error while parsing user credentials inside registration form Springboot

I need to complete the registration form on SpringBoot. To achieve this I created 2 classes : User and Credentials, the 2nd handles unique username and password.
#Getter
#Setter
#Entity
#Table(name = "users")
public class User {
public User() {}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
}
public class Credentials {
public static final String DEFAULT_ROLE = "DEFAULT";
public static final String ADMIN_ROLE = "ADMIN";
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Getter
#Column(nullable = false, unique = true)
private String username;
#Getter
#Column(nullable = false)
private String password;
#Getter
#Setter
#Column(nullable = false)
private String role;
#OneToOne(cascade = CascadeType.ALL)
private User user;
}
This is registrationController (handles "/registration" requests) :
#Controller
public class RegController {
#GetMapping("/register")
public String register(Model model){
model.addAttribute("user", new User());
model.addAttribute("credentials", new Credentials());
return "register";
}
}
Now it should be all set, ready to read data from html form and register new users using thymeleaf.
This is registration form inside registration.html, my goal is to read username and password then create a new user and save him on Postgres :
<body>
<div class="login">
<form id="login" method="POST" th:action="#{/register}">
<label><b>User Name
</b>
</label>
<input type="text" name="Uname" id="Uname" placeholder="Username" required th:field="${credentials.username}">
<br><br>
<label><b>Password
</b>
</label>
<input type="Password" name="Pass" id="Pass" placeholder="Password" required th:field="${credentials.password}">
<br><br>
<label><b>Repeat Password
</b>
</label>
<input type="Password" name="RPass" id="RPass" placeholder="Password">
<br><br>
<button type="submit" class="btn btn-primary" id="log">Registrati</button>
<div style = "background-color:green">
<a id= "link" th:href="#{/login}" >or login</a>
</div>
</form>
</div>
</body>
But when I navigate to registration.html this is the error from TomCat :
Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing (template: "class path resource [templates/register.html]")
What I noticed is that if I remove all the th:field (used to get user input) the page is shown without error.
I noticed that your Credentials class has only getters for username and password. If Thymeleaf has to fill them with the user input, shouldn't you provide setters too?
#Getter
#Setter
#Column(nullable = false, unique = true)
private String username;
#Getter
#Setter
#Column(nullable = false)
private String password;

HTTP Status 500 - Request processing failed;nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

I am trying to add/update students but while updating student I am getting an error. But while adding student it works fine. I am getting this error while updating: -
HTTP Status 500 - Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
add-students.jsp
<form:form action="addStudent" enctype="multipart/form-data" modelAttribute="addstd" method="POST" >
<form:hidden path="id" />
${message}
<form:errors path="firstName" cssClass="error" />
<form:input path="firstName" placeholder="Fistname" />
<form:errors path="lastName" cssClass="error" />
<form:input path="lastName" placeholder="Lastname" />
<form:input path="contact_No" placeholder="Contact Number" />
<form:input path="address" placeholder="Address" />
<form:errors path="email" cssClass="error" />
<form:input path="email" placeholder="Email" />
<p class="msg">
Year:
<form:select path="year">
<c:forEach var="temp" items="${studentyear}">
<form:option value="${temp.yearId}">${temp.year}</form:option>
</c:forEach>
</form:select>
Faculty:
<form:select path="faculty">
<c:forEach var="temp" items="${studentfaculty}">
<form:option value="${temp.faculty_id}" >${temp.faculty}</form:option>
</c:forEach>
</form:select>
Profile: <input type="file" name="image" accept="image/*" />
</p>
<input type="submit" value="Add/Update Record" class="button" />
</form:form>
#Controller class
#RequestMapping(value="/addStudent",method=RequestMethod.POST)
public String saveStudent(#RequestParam("image") MultipartFile file,#RequestParam("id") int theId,#ModelAttribute("addstd") #Valid StudentInfo theStudent,BindingResult result,Model model){
String fileName=null;
if(!file.isEmpty()){
try {
String path= session.getServletContext().getRealPath("/resources/images");
String newName=String.valueOf(new java.util.Date().getTime());
fileName=file.getOriginalFilename();
String ext=FilenameUtils.getExtension(fileName);
if(ext.equalsIgnoreCase("jpg") || ext.equalsIgnoreCase("jpeg") || ext.equalsIgnoreCase("png")){
File imageFile=new File(path,newName+"."+ext);
file.transferTo(imageFile);
theStudent.setImages(newName+"."+ext);
if(theId!=0){
StudentInfo std=studentService.getStudent(theId);
String images= std.getImages();
File oldImage=new File(path,images);
Files.delete(oldImage.toPath());
}
}
} catch (Exception e) {
}
}
if(result.hasErrors()){
List <Year> theYear = studentService.getYear();
model.addAttribute("studentyear",theYear);
List<Faculty> theFaculty=studentService.getFaculty();
model.addAttribute("studentfaculty",theFaculty);
return "add-students";
}else{
studentService.saveStudent(theStudent);
return "redirect:/login";
}
}
#RequestMapping("/showFormForUpdate")
public String showUpdateStudent(#RequestParam("studentId") int theId, Model model){
StudentInfo theStudent=studentService.getStudent(theId);
model.addAttribute("addstd",theStudent);
List <Year> theYear = studentService.getYear();
model.addAttribute("studentyear",theYear);
List<Faculty> theFaculty=studentService.getFaculty();
model.addAttribute("studentfaculty",theFaculty);
return "add-students";
}
StudentDAOImpl.class
public void saveStudent(StudentInfo theStudent) {
Session currentSession=sessionFactory.getCurrentSession();
currentSession.saveOrUpdate(theStudent);
}
StudentInfo.class
#Entity
#Table (name="studentinfo")
public class StudentInfo implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="year_id")
private int year;
#Column(name="faculty_id")
private int faculty;
#NotEmpty(message="First Name cannot be empty")
#Column(name="firstname")
private String firstName;
#NotEmpty(message="Last Name cannot be empty")
#Column(name="lastname")
private String lastName;
#Column(name="contact_no")
private String contact_No;
#Column(name="address")
private String address;
#Email(message="Enter a valid email address")
#Column(name="email")
private String email;
#Column(name="images")
private String images;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="ID")
private User user;
//getter and setter here
User.class
#Entity
#Table(name="user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_id")
private int user_id;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#OneToOne(mappedBy = "user",fetch = FetchType.LAZY)
private StudentInfo info;
//getter and setter here
In your StudentInfo class there is one field:
private User user;
You have not mapped user with any field in your form controller.
You can map your user like this:
<form:hidden path="user.user_id"/>
If you want to allow this value as null then provide
nullable = true
in your one-to-one annotation and also allow null in db.
If you are doing add student and you have not user nullable then you will have to somehow inject user into your controller.
For example, in your controller method while adding new StudentInfo get user info from database and then inject in studentInfo. I have written sudo code as below:
// User user = session.get(User.class, 1);
// studentInfo.setUser(user);
// saveorUpdate studentInfo

Save a form in jsp with dropdown listfrom from database in Spring MVC

I'm trying to save Account object in the hibernate .please find the following code.
#RequestMapping(value = "/saveAccount", method = RequestMethod.POST)
public ModelAndView saveAccount(#ModelAttribute("account") Account account,
BindingResult result) {
Session session = sessionFactory.openSession();
System.out.println(account.getFirstName());
System.out.println(account.getLastName());
System.out.println(account.getSubject());
System.out.println(account.getCity().getCityName());
session.save(account);
return new ModelAndView("redirect:/form.html");
}
My jsp page have a form with First Name,Last Name ,city and subject fields.
I'm getting city dropdown fromatabase.
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib
prefix="c"
uri="http://java.sun.com/jsp/jstl/core"
%>
<!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>
<h3>Contact Form</h3>
<div class="container">
<form method="post" action="/sdnext/saveAccount.html">
<label for="fname">First Name</label>
<input type="text" id="fname" name="firstName" placeholder="Your name..">
<label for="lname">Last Name</label>
<input type="text" id="lname" name="lastName" placeholder="Your last name..">
<label for="country">City</label>
<select name="city" id="cityName" >
<c:forEach var="cityname" items="${lists}">
<option value="${cityname.cityName}">${cityname.cityName}</option>
</c:forEach>
</select>
<label for="subject">Subject</label>
<textarea id="subject" name="subject" placeholder="Write something.." style="height:200px"></textarea>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
DataBase bean classes are here
package test.*;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name= "Account")
public class Account implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
private String firstName;
private String LastName;
#OneToOne
private City city;
private String subject;
}
package test.*;
#Entity
#Table(name= "City")
public class City implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private String cityName;
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
}
I have used one to one mapping to city object.But i'm not able to save city object in database,rest all firstNme,LastName and subjects are getting saved.its showing in network console,but data is not getting saved in database.Please help me fix this.Thanking you..
By creating the dto we can persists the values selected from the dropdown.and its working for me .
<option value="${cityname}">${cityname.cityName}</option>
The problem is you are sending cityname.cityName (String) which cannot be mapped to City object so,
send the complete city object as the value. Hibernate will take care of mapping.

Resources