how to validate email spring boot thymeleaf - spring-boot

I Want to validate e-mail when user want to register at my website. I set #NotBlank and #Email annotations, made #Valid annotation at post method, but I don't know how to make it work properly. At /register endpoint application shows error500. How can I change my code to make it work? Username shouldn't register with blank or incorrect email, but I can't solve it.
AppUser class:
#Data
#Entity
public class AppUser implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
#NotBlank(message = "login is required")
private String username;
#NotBlank(message = "password is required")
private String password;
private String role;
#Column(unique = true)
#Email(message = "Wrong e-mail")
private String email;
private String phone;
public AppUser() {
}
UserController class:
#Controller
public class UserController {
#GetMapping("register")
public String register(Model model) {
model.addAttribute("user", new AppUser());
return "register";
}
#PostMapping("/registerOk")
public String registerOk(#Valid AppUser appUser, Errors errors) {
if (errors.hasErrors()) {
return "register";
}
userService.addUser(appUser);
return "redirect:register?success";
}
}
My register.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Rejestracja</title>
<link rel="stylesheet" type="text/css" th:href="#{/css/index.css}"/>
</head>
<body>
<form class="box" th:action="#{/registerOk}" method="post">
<div th:if="${param.success}">
<div class="alert alert-info"><span style="color: white">Register is sucessful, check your e-mail adress.</span></div>
</div>
<h1>Register new account: </h1>
<input type="text" name="username" placeholder="login">
<span class="validationError"
th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">Username Error</span>
<input type="password" name="password" placeholder="password" id="hide">
<input type="text" name="email" placeholder="E-Mail">
<input type="text" name="phone" placeholder="phone number">
<input type="submit" value="Register me!">
<div class="form-group">
<span style="color: white">Already registered? Login</span>
</div>
</form>
</body>
</html>

Use type="email" instead of text.
<input type="email" name="email" placeholder="E-Mail">
Use required if you would like the input field as mandatory input.
<input type="email" name="email" placeholder="E-Mail" required>

Related

Cannot connect Thymeleaf HTML webpage to my Spring Boot API/DB

I have a Spring Boot application for a school records management system. My API is working perfectly when using Insomnia but I cannot get my hTML webpage to interact with the API. Here are the relevant bits of my Staff entity/controller/repository/service. Any help appreciated!
Entity class:
#Entity
#Data
#Embeddable
#NoArgsConstructor
#AllArgsConstructor
#Builder
#ToString
public class Staff {
#Id
#SequenceGenerator(
name = "STAFF_SEQ",
sequenceName = "STAFF_SEQ",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "STAFF_SEQ"
)
private Long staffId;
private String firstName;
private String lastName;
private String staffEmail;
#ManyToOne(targetEntity = Department.class)
private Long departmentId;
private String address;
private String contactNumber;
private char gender;
}
...
}
Controller Class
#RestController
public class StaffController {
#Autowired
private StaffService staffService;
#RequestMapping(value = "/saveStaff")
public Staff saveStaff(Staff staff) {
return staffService.saveStaff(staff);
}
...
}
Repository Class
#Repository
public interface StaffRepository extends JpaRepository<Staff, Long> {
Staff findByFirstNameAndLastName(String firstName, String lastName);
}
Service Interface
public interface StaffService {
public Staff saveStaff(Staff staff);
...
}
ServiceImpl
#Service
public class StaffServiceImpl implements StaffService{
#Autowired
StaffRepository staffRepository;
#Override
public Staff saveStaff(Staff staff) {
return staffRepository.save(staff);
}
...
}
HTML file
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<h2>Add Staff</h2>
<form action = "#" method="post" th:action ="#{/saveStaff}" th:object = "${staff}">
<fieldset>
<legend>Staff</legend>
<label for="firstName">First name:</label><br>
<input type="text" th:field ="*{firstName}" class="form-control" id="firstName" name="firstName"><br><br>
<label for="lastName">Last name:</label><br>
<input type="text" th:field ="*{lastName}" class="form-control" id="lastName" name="lastname"><br><br>
<label for="staffEmail">Staff email:</label><br>
<input type="staffEmail" th:field ="*{staffEmail}" class="form-control" id="staffEmail" name="staffEmail"> <br><br>
<label for="address">Address</label><br>
<input type="text" th:field ="*{address}" class="form-control" id="address" name="address"><br><br>
<label for="contactNumber"> Contact number</label><br>
<input type="text" th:field ="*{contactNumber}" class="form-control" id="contactNumber" name="contactNumber"><br><br>
<label for="gender">Gender:</label>
<select th:field ="*{gender}" class="form-control" id="gender" name="gender">
<option value="f">F</option>
<option value="m">M</option>
</select><br><br>
<label for="departmentId"> Department Id</label><br>
<input type="number" th:field ="*{departmentId}" class="form-control" id="departmentId" name="departmentId"><br><br>
<input type="submit" value="Submit">
<input type="reset">
</fieldset>
</form>
</body>
</html>
Your controller class is a #RestController. From view page you need to call the rest controller by using XmlHttpRequest or we can say, Ajax request or fetch API. For your ease, you can try jQuery. If you really want to submit your form the Thymeleaf way, then your controller needs to be a MVC Controller. Long story short, you should replace the annotation #RestController with #Controller. Also remove the action attribute and keep only th:action.
Your Controller class
#Controller
#RequestMapping("/course")
public class CourseController {
#Autowired
CourseService courseService;
#GetMapping("/add")
public String get_saveCourseForm(Model model) {
Course course = new Course();
model.addAttribute("course", course);
return "saveCourse";
}
#PostMapping("/save")
public String post_saveCourseForm(#ModelAttribute("course") Course course, Model model) {
courseService.saveCourse(course);
var courses = courseService.fetchCourseList();
model.addAttribute("courses", courses);
return "displayCourses";
}
}
Replaced #RestController with #Controller annotation
Add MVC methods and return view page names from the MVC methods. Also notice the request mappings. We will view the form by calling /course/add and the form will be submitted to /course/save.
Your Form Page
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<h2>Add Course</h2>
<form method="post" th:action ="#{/course/save}" th:object = "${course}">
<fieldset>
<legend>Staff</legend>
<label for="courseName">Course name:</label><br>
<input type="text" th:field ="*{courseName}" class="form-control" id="courseName" name="courseName"><br><br>
<label for="courseCode">Course code:</label><br>
<input type="text" th:field ="*{courseCode}" class="form-control" id="courseCode" name="courseCode"><br><br>
<label for="departmentId"> Department Id</label><br>
<input type="number" th:field ="*{departmentId}" class="form-control" id="departmentId" name="departmentId"><br><br>
<input type="submit" value="Submit">
<input type="reset">
</fieldset>
</form>
</body>
</html>
Check the form action.
The page will look like below.
When the form will be submitted, it will return the result page. the HTML code is as follows.
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Display Courses</title>
</head>
<body>
<table>
<tr>
<th>Course ID</th>
<th>Course Name</th>
<th>Course Code</th>
</tr>
<tr th:each="course : ${courses}">
<td><span th:text="${course.courseId}"></span></td>
<td><span th:text="${course.courseName}"></span></td>
<td><span th:text="${course.courseCode}"></span></td>
</tr>
</table>
</body>
</html>
The page will look as follows.

How to fix ModelAttributes are return null value?

I'm setting up a spring project, I want to make user registration functionality. I want to submit user data to spring controller and receive data by a #ModelAttribute, But ModelAttribute returns some values properly but some doesn't.
this is my user bean.
public class User {
private Long id;
private String userName;
private String password;
private String email;
private Date regdate;
private String loginId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return userName;
}
public void setUsername(String username) {
this.userName = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getRegdate() {
return regdate;
}
public void setRegdate(Date regdate) {
this.regdate = regdate;
}
public String getLoginId() {
return loginId;
}
public void setLoginId(String loginId) {
this.loginId = loginId;
}
}
this is form I want to submit.
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="register" method="post" modelAttribute="user">
<label for="loginid">ID:</label>
<input type="text" name="loginid">
<label for="password">password :</label>
<input type="password" name="password">
<label for="username">username :</label>
<input type="text" name="username">
<label for="email">e-mail :</label>
<input type="text" name="email">
<input type="submit" name="submit" value="submit"/>
</form>
</body>
</html>
so I printed out model attribute to log data out.
System.out.println("loginid :"+user.getLoginId()+"username :"+user.getUsername()+" password :"+ user.getPassword());
and it returned loginid :null username :user password :user
this is controller that I receive data. I tried to get a data by a ModelAttribute Annotation
#RequestMapping(value="/register", method=RequestMethod.POST)
public String createUser(#ModelAttribute User user, HttpServletRequest request, Model model) {
String ip = request.getRemoteAddr().toString();
System.out.println("loginid :"+user.getLoginId()+"id :"+user.getId()+"username :"+user.getUsername()+"password :"+ user.getPassword());
try {
userService.addUser(user,ip);
return "registrationsuccess";
}catch(Exception e) {
e.printStackTrace();
}
return "registrationfail";
}
Try to look here
Maybe you have not RequestMapping in your Post method?
P.S
Try to change
<form action="register" method="post" modelAttribute="user">
<label for="loginid">ID:</label>
<input type="text" name="loginid">
<label for="password">password :</label>
<input type="password" name="password">
<label for="username">username :</label>
<input type="text" name="username">
<label for="email">e-mail :</label>
<input type="text" name="email">
<input type="submit" name="submit" value="submit"/>
</form>
to
<form:form method="post" action="/register" modelAttribute="user">
<form:label path="loginid">ID:</form:label>
<form:input path="loginid" />
<form:label path="password">password:</form:label>
<form:input path="password" />
...
<input type="submit" value="submit" />
</form:form>
In your controller, try to change
public String createUser(#ModelAttribute User user, HttpServletRequest request, Model model)
to
public String createUser(#ModelAttribute("user") User user, HttpServletRequest request, Model model)

I can not update my entity using Hibernate, Spring MVC, Thymleaf

Hello I want to update User entity, so in the form edit.html i'm using thymeleaf:
<form action="#" th:action="#{/{id}/edit(id=${user.id})}"
th:object="${user}" method="post">
<div class="md-form">
<input type="text" th:field="*{firstName}"
th:value="${user.firstName}" name="firstName" id="firstName"
class="form-control" /> <label class="active" for="firstName">Prénom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{lastName}"
th:value="${user.lastName}" name="lastName" id="lastName"
class="form-control" /> <label class="active" for="lastName">Nom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{email}" th:value="${user.email}"
name="email" id="email" class="form-control" /> <label
class="active" for="email">email</label>
</div>
<div class="md-form">
<input type="text" th:field="*{password}"
th:value="${user.password}" name="password" id="password"
class="form-control" /> <label class="active" for="password">mot
de passe</label>
</div>
<div class="md-form">
<input type="text" th:field="*{occupation}"
th:value="${user.occupation}" name="occupation" id="occupation"
class="form-control" /> <label class="active" for="occupation">profession</label>
</div>
<div class="md-form">
<input type="text" th:field="*{ville}" th:value="${user.ville}"
name="ville" id="ville" class="form-control" /> <label
class="active" for="ville">ville</label>
</div>
<div>
<input class="btn btn-sm btn-primary waves-effect btn-rounded"
type="submit" value="modifier" />
</div>
</form>
User.java:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String userName;
private int age;
private String ville;
private String email;
private String password;
private String phone;
private String company;
private String occupation;
private String img_profil;
#ManyToMany(mappedBy = "users", cascade = { CascadeType.ALL })
private Set<Discussion> discussion;
UserController.java
#GetMapping("/{userName}/edit")
public String editUser(#PathVariable String userName, Model model) {
User user = ur.findByUserName(userName).get(0);
model.addAttribute(user);
return "edit";
}
#PostMapping("/{id}/edit")
public String updateUser(#ModelAttribute("user") User user, #PathVariable("id") Long id) {
user = ur.findOne(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}
UserRepository.java
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByUserName(String userName);
}
PROBLEM is in the console I do not see update request (generated by Hibernate), nothing is changed on the database.
Make the following change in UserController.java:
#PostMapping("/{id}/edit")
public String updateUser(
#ModelAttribute("user") User user,
#PathVariable("id") Long id)
{
//user = ur.findOne(id);
user.setId(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}

Spring boot Mongodb Creating a nested document

can any one please tell me what I am missing ?
I am trying to create a Mongo collection using spring boot mongodb.
I want to create something like this
{
"_id":"123456"
"entity_name":"some name"
"entity_desc":"some description"
"events":[
{"title":"some title", "description":"some description"},
{"title":"title2", "description":"description2" }
]
}
but I am getting this
{
"_id":"123456"
"entity_name":"some name"
"entity_desc":"some description"
"events":[ ]
}
my Domain classes are
#Document
public class Entity {
#Id
private BigInteger id;
private String name, description;
private List<Event> events=new ArrayList<Event>();
/* GETTERS AND SETTERS */
}
public class Event {
private String titles;
private String descriptions;
/* GETTERS AND SETTERS */
}
and my repository is
public interface MyRepository extends MongoRepository<Entity, String>{
}
controller is
#Controller
public class RootController {
#Autowired
private MyRepository mr;
/* GET and other methods */
#RequestMapping(value="/", method=RequestMethod.POST)
public String helloPost(#ModelAttribute Entity entity){
mr.save(entity);
return "success";
}
}
and my jsp form is
<form:form modelAttribute="entity" role="form">
<div class="form-group">
Name <input type="text" id="name" name="name" /><br />
</div>
<div class="form-group">
Description <input type="text" id="description" name="description" /><br />
</div>
<div class="form-group">
event <input type="text" id="event" name="event" /><br />
</div>
<div class="form-group" >
title <input type="text" id="title" name="title" /><br />
</div>
<div class="form-group" >
description <input type="text" id="description" name="description" /><br />
</div>
<div>
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form:form>
Shouldn't it be something like below?
public class Event {
private String title;
private String description;
/* GETTERS AND SETTERS */
}
EDIT : Thanks for the jsp, clearly the way you are passing the values are not picked for child. Spring MVC doesn't support ONGL so it won't pick up child object with dot notation. But there are complex mechanism by setting path. Please look at this answer where it did pass child object list through form parameter. So it can be good starting point.

Spring validator - The request sent by the client was syntactically incorrect

My friend helped me up set my first spring/hibernate project and now I am trying to implement a custom validator. I already have a RegistrationForm model that uses anotations to validate. However, now I need to implement a password validator - to check if the password and confirmPassword are equal.
Problem: when I POST, if the passwords match, the data is saved. If they dont match, then at the validators following line, I get the error from the title.
errors.rejectValue("confirmPassword", "valid.passwordConfDiff");
The request sent by the client was syntactically incorrect.
Tutorial I followed:
http://examples.javacodegeeks.com/enterprise-java/spring/mvc/spring-mvc-password-example/
This is what I have:
Controller:
#Controller
#RequestMapping("/")
//#SessionAttributes(value = {"registerForm"})
#ComponentScan("ba.codecentric.movienight")
public class FrontController {
#Autowired
private UserService userService;
#Autowired
#Qualifier("passwordValidator")
private PasswordValidator validator;
#InitBinder("password")
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
#RequestMapping(method = RequestMethod.GET)
public String initIndex(Model model){
model.addAttribute("registerForm", new RegisterForm());
Password password = new Password();
model.addAttribute("password", password);
return "index";
}
#RequestMapping(value="/register", method=RequestMethod.POST)
public String addNewUser(#Valid #ModelAttribute("registerForm") RegisterForm registerForm,
BindingResult result, Model model, HttpServletRequest request, #Validated Password password){
if(result.hasErrors()){
model.addAttribute("error", true);
model.addAttribute("userIsRegistering", "<script>$('#loginbox').hide(); $('#signupbox').show();</script>");
System.out.println("ERROR");
return "index";
}
User user = new User();
user.setUserName(registerForm.getUserName());
user.setPassword(registerForm.getPassword());
userService.addNewUser(user);
return "index";
}
}
Password validator:
public class PasswordValidator implements Validator{
public boolean supports(Class<?> paramClass) {
return Password.class.equals(paramClass);
}
public void validate(Object obj, Errors errors) {
Password password = (Password) obj;
if (!password.getPassword().equals(password.getConfirmPassword())) {
errors.rejectValue("confirmPassword", "valid.passwordConfDiff");
}
}
}
RegistrationForm:
public class RegisterForm {
#NotBlank
#NotEmpty
private String userName;
#NotBlank
#NotEmpty
#Size(min=7,max=16,message="Password range error")
private String password;
#NotBlank
#NotEmpty
private String confirmPassword;
//getters setters
}
Registration form jsp:
<form:form id="signupform" class="form-horizontal" role="form" commandName="registerForm" action="${pageContext.request.contextPath}/register" method="post">
<form:errors path="*" cssClass="errorblock" element="div" class="alert alert-danger" role="alert" />
<div class="form-group">
<label for="userName" class="col-md-3 control-label">User Name</label>
<div class="col-md-9">
<form:input type="text" path="userName" class="form-control" name="userName" placeholder="User Name" />
</div>
</div>
<form:errors path="userName" element="div" class="alert alert-danger" role="alert" />
<div class="form-group">
<label for="password" class="col-md-3 control-label">Password</label>
<div class="col-md-9">
<form:password path="password" class="form-control" name="password" placeholder="Password"/>
</div>
</div>
<form:errors path="password" element="div" class="alert alert-danger" role="alert" />
<div class="form-group">
<label for="confirmPassword" class="col-md-3 control-label">Confirm Password</label>
<div class="col-md-9">
<form:password path="confirmPassword" class="form-control" name="confirmPassword" placeholder="Confirm Password"/>
</div>
</div>
<form:errors path="confirmPassword" class="alert alert-danger" role="alert" />
<div class="form-group">
<!-- Button -->
<div class="col-md-offset-3 col-md-9">
<form:button id="btn-signup" type="submit" class="btn btn-info"><i class="icon-hand-right"></i> &nbsp Sign Up</form:button>
</div>
</div>
</form:form>
I have also faced the same problem.
#RequestMapping(method = RequestMethod.POST)
public String processForm(
#Valid #ModelAttribute("student") Student student, Model model,
BindingResult result) {
if (result.hasErrors()) {
return "registration";
}
return "success";
}
When the object student has invalid attribute(s), then this code gives the error: The request sent by the client was syntactically incorrect.
However, if the order of arguments student and model is changed, then this method works as expected.
E.g.,
public String processForm(Model model, #Valid #ModelAttribute("student") Student student, BindingResult result)
and
public String processForm( #Valid #ModelAttribute("student") Student student, BindingResult result, Model model)
both work as expected.
Please, let me know what is the science behind this.

Resources