Form is not saved because it has errors, but errors are not displayed - spring

I have a SignUp form for user, also I have a validation for fields, I'll provide all of that. So, when user insert for example on field username > s but that field need to have more then 3 characters, program should show error and not save that data into table. What's happening? Application process the error, I mean form is not submitted when I made a error on purpose, but error is not showing on HTML, not on stack trace. Page is just returned but error message are not showing, good thing is just that form is not saved if there is error so that work, problem is just message not appearing.
I have a SignUp form, and for example I have this validation on username and firstName:
#NotEmpty
#Size(min = 3, max = 20, message = "Username not valid")
private String username;
#NotEmpty(message = "Please, insert a first name")
private String firstName;
This is how I display form, its login and register on same page, that is why I have two model attributes:
#GetMapping("/loginAndRegisterForm")
public String showLoginForm(Model model) {
// create model object to store form data
LoginRequest loginRequest = new LoginRequest();
SignupRequest signupRequest = new SignupRequest();
model.addAttribute("login", loginRequest);
model.addAttribute("user", signupRequest);
return "login_and_registration";
}
This is SignUp controller, with result.hasErrors() inside it:
#PostMapping("/signup")
#Transactional
public String signup(#ModelAttribute("signup") #Valid SignupRequest signupRequest, BindingResult result, Model model) throws Exception {
boolean thereAreErrors = result.hasErrors();
if (thereAreErrors) {
LoginRequest loginRequest = new LoginRequest();
model.addAttribute("user", signupRequest);
model.addAttribute("signup", signupRequest);
model.addAttribute("login", loginRequest);
return "login_and_registration";
}
User user = new User(signupRequest.getUsername(), signupRequest.getFirstName(), signupRequest.getLastName(), signupRequest.getEmail(), encoder.encode(signupRequest.getPassword()));
model.addAttribute("signup", signupRequest);
userRepository.save(user);
return "redirect:/api/auth/loginAndRegisterForm";
}
And this is Thymeleaf:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Security Tutorial</title>
<link rel="stylesheet" type="text/css" th:href="#{/css/loginAndRegistration.css}"/>
</head>
<body>
<div class="main">
<input type="checkbox" id="chk" aria-hidden="true">
<div class="signup">
<form
method="post"
role="form"
th:action="#{/api/auth/signup}"
th:object="${user}">
<label for="chk" aria-hidden="true">Sign up</label>
<input
class="form-control"
id="usernameSignUp"
name="username"
placeholder="Enter username"
th:field="*{username}"
type="text"/>
<p th:errors="*{username}" class="text-danger"
th:if="${#fields.hasErrors('username')}"></p>
<input
class="form-control"
id="firstName"
name="firstName"
placeholder="Enter first name"
th:field="*{firstName}"
type="text"/>
<p th:errors="*{firstName}" class="text-danger"
th:if="${#fields.hasErrors('firstName')}"></p>
<input
class="form-control"
id="lastName"
name="lastName"
placeholder="Enter lastName"
th:field="*{lastName}"
type="text"/>
<p th:errors="*{firstName}" class="text-danger"
th:if="${#fields.hasErrors('firstName')}"></p>
<input
class="form-control"
id="email"
name="email"
placeholder="Enter email"
th:field="*{email}"
type="email"/>
<p th:errors="*{email}" class="text-danger"
th:if="${#fields.hasErrors('email')}"></p>
<input
class="form-control"
id="passwordSignUp"
name="password"
placeholder="Enter password"
th:field="*{password}"
type="password"/>
<p th:errors="*{password}" class="text-danger"
th:if="${#fields.hasErrors('password')}"></p>
<button>Sign up</button>
</form>
</div>
<div class="login">
<form
method="post"
role="form"
th:action="#{/api/auth/login}"
th:object="${login}">
<label for="chk" aria-hidden="true">Login</label>
<input
class="form-control"
id="usernameLogin"
name="username"
placeholder="Enter username"
th:field="*{username}"
type="text"/>
<p th:errors="*{username}" class="text-danger"
th:if="${#fields.hasErrors('username')}"></p>
<input
class="form-control"
id="passwordLogin"
name="password"
placeholder="Enter password"
th:field="*{password}"
type="password"/>
<p th:errors="*{password}" class="text-danger"
th:if="${#fields.hasErrors('password')}"></p>
<button>Login</button>
</form>
</div>
</div>
</body>
</html>

Related

Property or field 'userName' cannot be found on null

here is the code:-
form.html :
<div class="container">
<div class="row mt-5">
<div class="col-md-6 offset-md-3">
<form th:action="#{/process}" method="post" th:object="${loginData}">
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input
type="text"
name="userName"
class="form-control"
th:value="${loginData.userName}"
id="exampleInputEmail1"
aria-describedby="emailHelp">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input
type="email"
name="email"
th:value="${loginData}"
class="form-control"
id="exampleInputPassword1">
</div>
<div class="mb-3 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>
MyController :
#GetMapping("/form")
public String formHandler(Model m ) {
System.out.println("opening form");
LoginData loginData = new LoginData();
if(loginData != null ) {
m.addAttribute("login", new LoginData());
System.out.println("YAY");
}else {
System.out.println("Bhag Bh*****ke");
}
return "form1";
}
//handler for process form
#PostMapping("/process")
public String processform(#ModelAttribute("loginData") LoginData loginData) {
System.out.println(loginData);
return"success";
}
success.html :
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Success</title>
</head>
<body>
<h1>Welcome to this success page</h1>
<h1 th:text="${LoginData.userName}"></h1>
<h1 th:text="${LoginData.email}"></h1>
</body>
</html>
saying error : Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'userName' cannot be found on null
Login page is not ruuning because LoginData is empty at begining
You haven't exactly specified which of the 2 pages are causing the issue, but I'm going to guess that it is the first one.
I would first try replacing the th:value tag with th:field in the username input:
<input
type="text"
name="userName"
class="form-control"
th:field="*{userName}"
id="exampleInputEmail1"
aria-describedby="emailHelp">
Since you have already defined the loginData object within the form tag:
th:object="${loginData}
The next input tag could also cause some issues, I'm guessing that this should accept the user's password:
<input
type="email"
name="email"
th:value="${loginData}"
class="form-control"
id="exampleInputPassword1">
You would want to update it to something like:
<input
type="password"
th:field="*{password}"
class="form-control"
id="exampleInputPassword1">
The exception tells you that there is no model attribute with the name loginData. looking at the controller code after this that can be confirmed as you are adding a model attribute with name login not loginData m.addAttribute("login", new LoginData());
Also I'm not usre why you define a loginData variable in your controller, check if it's non null and than don't use it but create a new one
LoginData loginData = new LoginData();
if(loginData != null ) {
m.addAttribute("login", new LoginData());
System.out.println("YAY");
}

The server cannot process the request because of Spring MVC <form:select>

I am creating a formular in order to populate some entities. I run into problems when I am trying to POST a form which contains a Spring MVC <form:select> field.
In Eclipse I do not receive any error or warning message, while in the browser I get a http status 400 - Bad Request.
Type Status Report
Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
Extra explanations:
I have a StudentDetails entity which contains 2 fields that I am interested in at the moment, Classroom classroom and ParentsDetails parentsDetails.
The Classroom objects are already created and all of them will be stored in a LinkedHashMap<Classroom, String> as a model attribute (i am doing this in the saveAccountDetails method from the Controller).
The ParentsDetails object will be created after the StudentDetails entity will be saved with the selected classroom.
When I submit the form as I mentioned above I run into an error but without any(or relevant) error message.
I spent some time debugging and trying different approaches of handling that map of Classrooms, but none of them worked.
What is actually happening, the controller method saveStudentDetails is not called anymore.
The issue must come from that form:select because if I get rid of this input, the controller method will be called and will let me advance in creating the ParentsDetails entity.
I have no clue what is wrong.
I used previously this form:select but the LinkedHashMap contained just Strings, without any objects and it worked. I think thats my issue.
StudentDetails.java
#Entity
#Table(name="student_details")
public class StudentDetails {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="current_year_of_study")
private Integer currentYearOfStudy;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="parents_details_id")
private ParentsDetails parentsDetails;
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name="class_id")
private Classroom classroom;
#OneToOne(mappedBy="studentDetails", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
private User user;
#ManyToMany
#JoinTable(name="course_studentdetails",
joinColumns=#JoinColumn(name="student_details_id"),
inverseJoinColumns=#JoinColumn(name="course_id")
)
private List<Course> courses;
... (Constructors, getters setters)
Controller.java
#PostMapping("/save-account-details")
public String saveAccountDetails(#ModelAttribute("theAccountDetails") AccountDetails theAccountDetails, #RequestParam("userUsername") String username, Model theModel) {
User theUser = userService.getUser(username);
theUser.setAccountDetails(theAccountDetails);
accountDetailsService.saveAccountDetails(theAccountDetails);
userService.saveUser(theUser);
theModel.addAttribute("theUser", theUser);
theModel.addAttribute("theStudentDetails", new StudentDetails());
theModel.addAttribute("classroomsList", classroomService.getSchoolClassrooms(theUser.getAccountDetails().getCity()));
theModel.addAttribute("entity", "StudentDetails");
return "create-user";
}
#PostMapping("/save-student-details")
public String saveStudentDetails(#ModelAttribute("theStudentDetails") StudentDetails theStudentDetails, #RequestParam("userUsername") String username, Model theModel) {
User theUser = userService.getUser(username);
theUser.setStudentDetails(theStudentDetails);
studentDetailsService.saveStudentDetails(theStudentDetails);
userService.saveUser(theUser);
theModel.addAttribute("theUser", theUser);
theModel.addAttribute("theParentsDetails", new ParentsDetails());
theModel.addAttribute("entity", "ParentsDetails");
return "create-user";
}
#PostMapping("/save-parents-details")
public String saveParentsDetails(#ModelAttribute("theParentsDetails") ParentsDetails theParentsDetails, #RequestParam("userUsername") String username, Model theModel) {
User theUser = userService.getUser(username);
theUser.getStudentDetails().setParentsDetails(theParentsDetails);
parentsDetailsService.saveParentsDetails(theParentsDetails);
userService.saveUser(theUser);
theModel.addAttribute("theUser", theUser);
theModel.addAttribute("theParentsDetails", new ParentsDetails());
theModel.addAttribute("entity", "ParentsDetails");
return "create-user";
}
create-user.jsp
<c:if test="${entity == 'StudentDetails'}">
<c:url var="saveStudentDetails" value="save-student-details">
<c:param name="userUsername" value="${theUser.username}" />
</c:url>
<form:form action="${saveStudentDetails}" modelAttribute="theStudentDetails" method="POST">
<form:hidden path="id" />
<div class="form-area">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Current Year of Study</span>
</div>
<form:input type="text" class="form-control" path="currentYearOfStudy" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="inputGroupSelect01">Classroom</label>
</div>
<form:select path="classroom" class="custom-select" id="inputGroupSelect01">
<form:option value="" label="Select classroom..." />
<form:options items="${classroomsList}" />
</form:select>
</div>
<button type="submit" class="btn btn-outline-secondary btn-block">Submit</button>
</div>
</form:form>
</c:if>
<c:if test="${entity == 'ParentsDetails'}">
<c:url var="saveParentsDetails" value="save-parents-details">
<c:param name="userUsername" value="${theUser.username}" />
</c:url>
<form:form action="${saveParentsDetails}" modelAttribute="theParentsDetails" method="POST">
<form:hidden path="id" />
<div class="form-area">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Father First Name</span>
</div>
<form:input type="text" class="form-control" path="fatherFirstName" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Father Last Name</span>
</div>
<form:input type="text" class="form-control" path="fatherLastName" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Father Telephone</span>
</div>
<form:input type="text" class="form-control" path="fatherTelephone" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Mother First Name</span>
</div>
<form:input type="text" class="form-control" path="motherFirstName" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Mother Last Name</span>
</div>
<form:input type="text" class="form-control" path="motherLastName" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Mother Telephone</span>
</div>
<form:input type="text" class="form-control" path="motherTelephone" aria-label="Default" aria-describedby="inputGroup-sizing-default" />
</div>
<button type="submit" class="btn btn-outline-secondary btn-block">Submit</button>
</div>
</form:form>
</c:if>
If any more code snippets are needed, I will add them as soon as possible. Thank you in advance!
This is the network tab. The object looks like it was submitted with the form...
I will add shortly a video with the application.
Edit: demo link: https://youtu.be/neJOLHL9REo
Try adding multipart form-data to enctype in the form tag, it may works.
FROM:
<form:form action="${saveStudentDetails}"
modelAttribute="theStudentDetails" method="POST">
TO:
<form:form action="${saveStudentDetails}" enctype="multipart/form-data"
modelAttribute="theStudentDetails" method="POST">

Vue.js Asp.NET core Form validation

I am currently learning vuejs with asp .net core right now.
I am doing some form validation and adding some error messages.
The error messages are from the Server side here is my sample code:
[HttpPost]
public async Task<IActionResult> AddUser([FromBody] UserModel user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (_context.Users.Any(u => u.UserName == user.UserName))
{
ModelState.AddModelError("UserName", "Username is already in used");
return BadRequest(ModelState);
}
try
{
var userDto = new User
{
FirstName = user.FirstName,
LastName = user.LastName,
Password = user.Password,
UserName = user.UserName
};
_context.Users.Add(userDto);
await _context.SaveChangesAsync();
}
catch(Exception e)
{
ModelState.AddModelError("Saving Error", string.Format("Error in saving user. \nDetails:\n {0}", e.Message));
return BadRequest(ModelState);
}
return Ok();
}
And in the view:
<form v-on:submit.prevent="SaveUser()">
<div class="form-group">
<label for="userName">User Name</label>
<input class="form-control" type="text" id="userName" placeholder="Username" v-model="userName" required :disabled="isEditMode" />
</div>
<div class="form-group">
<label for="userName">First Name</label>
<input class="form-control" type="text" id="firstName" placeholder="First Name" v-model="firstName" required />
</div>
<div class="form-group">
<label for="userName">Last Name</label>
<input class="form-control" type="text" id="lastName" placeholder="Lastname" v-model="lastName" required />
</div>
<div v-if="!isEditMode">
<div class="form-group">
<label for="userName">Password</label>
<input class="form-control" type="password" id="password" placeholder="Password" v-model="password" required />
</div>
</div>
<!--TODO: Distribute to each control-->
<div v-if="hasError">
<ul v-for="error in errors">
<li style="color: red;" v-for="detail in error">{{detail}}</li>
</ul>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" #click="backToList()" class="btn btn-danger">Cancel</button>
</form>
Basically I am doing the validations from the server-side.
Currently the error messages are displayed below the controls
And I need to distribute all the error message inline with the inputs.
Can you help me with this?
Thanks in advance.

Spring MVC :- Form Submission (HTTP Status 400 - The request sent by the client was syntactically incorrect.)

There are two forms each having one submit button in my jsp page ... I want to send form 1 to my controller which consists of two images and few form fields.
Controller.java
#RequestMapping(value="/schoolDetails",method=RequestMethod.GET)
public ModelAndView getschoolDetails(){
ModelAndView model = new ModelAndView();
School schools=new School();
Map referenceData = new HashMap();
referenceData.put("schoolObject", schools);
ModelAndView mav = new ModelAndView("schoolDetails", referenceData);
return mav;
}
#RequestMapping(value="/addSchoolDetails",method=RequestMethod.POST)
public String addSchoolDetails(#ModelAttribute("schoolObject") School school,
#RequestParam("image") MultipartFile image,#RequestParam("logo") MultipartFile logo){
if(result.hasErrors()){
return "schoolDetails"; }
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
CustomUser user=null;
if (principal instanceof CustomUser) {
user = ((CustomUser)principal);
}
return "schoolDetails";
}
schoolDetails.jsp
<form:form method="POST" role="form" action="/GenericApp/addSchoolDetails" enctype="multipart/form-data" modelAttribute="schoolObject">
<div class="col s3" id="sName">School Name :</div>
<input id="form_text" name="schoolname" type="text" placeholder="School Name"/>
<div class="col s3" id="sName">Email ID :</div>
<input id="form_text" name="email" type="email" placeholder="Email ID"/>
<div class="col s3" id="sName">State :</div>
<select name="state" id="state_id" >
<option>State</option>
<option>Karnataka</option>
</select>
<div class="col s12 m4 l4" id="sName">Upload School Logo :</div>
<input type="file" name="logo" id="fileUpload" accept="image/x-png, image/gif, image/jpeg"/>
<span class="button teal ">Choose a Image</span>
<button class="waves-effect waves-light btn" type="submit" name="action">Submit</button>
</form:form>
As your jsp does not contain any tag having name image correct your jsp file by adding tag with name image also , as below
<form:form method="POST" role="form" action="/GenericApp/addSchoolDetails" enctype="multipart/form-data" modelAttribute="schoolObject">
<div class="col s3" id="sName">School Name :</div>
<input id="form_text" name="schoolname" type="text" placeholder="School Name"/>
<div class="col s3" id="sName">Email ID :</div>
<input id="form_text" name="email" type="email" placeholder="Email ID"/>
<div class="col s3" id="sName">State :</div>
<select name="state" id="state_id" >
<option>State</option>
<option>Karnataka</option>
</select>
<div class="col s12 m4 l4" id="sName">Upload School Logo :</div>
<input type="file" name="logo" id="fileUpload" accept="image/x-png, image/gif, image/jpeg"/>
<span class="button teal ">Choose a Image</span>
<input type="file" name="image" id="image" accept="image/x-png, image/gif, image/jpeg"/>
<button class="waves-effect waves-light btn" type="submit" name="action">Submit</button>
</form:form>

Cannot submit a form on SpringMVC

I am fairly new to SpringMVC and have a form that can not submit to the back-end. I created the form as following and when I submit it error 404 will be returned. I changed action to /MyProject/contact but did not work.
<form class="form-horizontal" role="form" method="post"
action="/contact">
<div class="form-group">
<div class="col-md-12">
<label class="sr-only" for="exampleInputName2">Name
</label> <input type="text" class="form-control" id="name"
name="name" placeholder="Your name" value="">
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<label class="sr-only" for="exampleInputName2">Email
Address</label> <input type="email" class="form-control" id="email"
name="email" placeholder="Your email" value="">
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<label class="sr-only" for="exampleInputName2">Phone
Number</label> <input type="number" class="form-control" id="phone"
name="phone" placeholder="Phone number" value="">
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<label class="sr-only" for="exampleInputName2">Enquiry</label>
<textarea class="form-control" rows="4" name="message"
placeholder="Please enter your enquiry"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-md-2 " style="float: right;">
<input id="submit" name="submit" type="submit" value="Send"
class="btn btn-primary">
</div>
</div>
<div class="form-group">
<div class="col-sm-10 col-sm-offset-2">
<! Will be used to display an alert to the user>
</div>
</div>
</form>
Controller
#Controller
public class ContactController {
#RequestMapping(value="/contact", method=RequestMethod.POST)
public String processForm(Contact contact, Model model){
System.err.println("Contact Name is:" + contact.getName());
return null;
}
}
Error
HTTP Status 404 - /contact
type Status report
message /contact
description The requested resource is not available.
Its beacuse spring does not know how to pass the param Contact contact to your controller method. You need to do couple of things to make it work. Change your form to like below.
<form class="form-horizontal" role="form" method="post" modelAttribute="contact" action="/contact">
Your controller to take contact as model attribute.
#Controller
public class ContactController {
#RequestMapping(value="/contact", method=RequestMethod.POST)
public String processForm(#ModelAttribute Contact contact, Model model){
System.err.println("Contact Name is:" + contact.getName());
return null;
}
}
For a better understanding of what a model attribute does, there are plenty of samples and explanation online. Hope this helps.
I could solve the problem by help of minion's answer, following this tutorial and adding following link
#RequestMapping(value = "/contact", method = RequestMethod.GET)
public ModelAndView contactForm() {
System.err.println("here in GET");
return new ModelAndView("contact", "command", new Contact());
}

Resources