I'm currently working on a usermanagement system for a website with Java Spring Boot, Thymeleaf, and Salespoint Framework for a university project.
On pages where users can edit their infos e.g. email or password, I use a validation of the form in which the data is stored via the @Valid annotaion. If the BindingResult has errors it should return to the same page to show the user the inputs where something was wrong. I used this on the following page to create a new user and it just works fine:
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/createmember")
public String createMember(@ModelAttribute("creationForm CreationForm creationForm) {
return "/createmember";
}
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/createmember")
public String createMember(@Valid @ModelAttribute("creationForm") CreationForm creationForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "/createmember";
}
//function to create new member
return "redirect:/memberlist";
}
The error message is implemented in the html page like this:
<td>
<input id="username" name="username" th:field="*{username}" required type="text" placeholder="Username">
<p th:if="${#fields.hasErrors('username')}" th:errors="*{username}"class="invalidinput">username errors</p>
</td>
The problem starts as soon as I want to use this for a page with a dynamic URL. In the following code, I want to change a users' password as a logged-in admin. For everything in the system to know which user currently is edited I use a dynamic URL password/{username}. The pure changing of the password also works fine as long as I don't check whether the password meets my validation requirements. It changes the users' password, if the newPassword and confirmationPasswordare the same, and if they are not, it doesn't change the password.
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("password/{username}")
public String password(@PathVariable String username, PasswordForm passwordForm) {
passwordForm.setUsername(username);
model.addAttribute("passwordForm", passwordForm);
return "/password";
}
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/password")
public String password(@Valid @ModelAttribute PasswordForm passwordForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "/password";
}
if (//checks if both passwords are equal) {
//function to change password
return "redirect:/memberlist";
}
return "redirect:/";
}
The HTML is equal to createMember.
The problem here is now that as soon as I give the form invalid inputs and submit the form, thymeleaf throws an error:
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'passwordForm' available as a request attribute
And some other errors caused by this.
If I change the code to
if (bindinResult.hasErrors()) {
return "/password/" + passwordForm.getUsername();
}
Thymeleaf can't find the template "/password/username".
However, if I change the code to:
if (bindinResult.hasErrors()) {
return "redirect:/password/" + passwordForm.getUsername();
}
It reloads the page without problems, but everything is gone and it doesn't show any errors, so this is not an option.
I hope this is not too much, I searched a while for solutions on the web but there were none.
Does anyone have any idea what could be the problem?