How to display RequestParam errors in Thymeleaf - java

I want to use a form without an object. How to display errors?
Controller:
#PostMapping(value="/submit")
public String doSubmit(#RequestParam("myParameter") String param, BindingResult bindingResult) {
bindingResult.rejectValue("myParameter", "Oh nooo!!!!");
return "html";
}
HTML:
<form th:action = "#{/submit}" method="post">
<label for="myParameter" class="form-label">My Parameter</label>
<input name="myParameter" class="form-control" type="text"/>
<span class="text-danger" th:if="${#fields.hasErrors('myParameter')}" th:errors="myParameter">Error</span>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
th:if="${#fields.hasErrors('myParameter')}" th:errors="myParameter" throws errors, cause "myParameter" is not known.
How to display the error, without using th:object in <form>

I did it with the help of this question Thymeleaf: display global errors by error code
#PostMapping(value="/submit")
public String doSubmit(#RequestParam("myParameter") String param, BindingResult bindingResult) {
bindingResult.reject("myParameter", "myParameter");
return "html";
}
Important: myParameter must not be a key of a message source!
<form th:action="#{/submit}" method="post">
<label for="myParameter" class="form-label">My Parameter</label>
<input name="myParameter" class="form-control" type="text"/>
<span class="text-danger" th:if="${#lists.contains(#fields.globalErrors(), "myParameter")}" th:text="An Error happened">Error</span>
<button type="submit" class="btn btn-primary">Submit</button>
Important: Use " to indicate the string. th:text? may contain a message key like th:text="#{error.code1}"`.

Related

Cannot get value from simple form user input in Spring boot application?

I'm trying to implement a login form in a Spring boot application. It has an email and a password field. The email field failed to get user input, here is the form:
<form th:action="#{/login}" method="get" th:object="${loginForm}" style="max-width: 600px; margin: 0 auto;">
<div class="m-3">
<div class="form-group row">
<label class="col-4 col-form-label">E-mail: </label>
<div class="col-8">
<input type="text" th:field="*{email}" name="q" class="form-control" required />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Password: </label>
<div class="col-8">
<input type="password" th:field="*{password}" class="form-control" required/>
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Log in</button>
</div>
</div>
</form>
Here is the controller:
#GetMapping("login")
public ModelAndView login(Model model, #RequestParam(name = "q", required = false) Optional<String> email) {
Optional<UserDto> aUser;
System.out.println(email);
if (email.isPresent()) {
aUser = userService.getAUserByEmail(email.get());
model.addAttribute("user", aUser);
var mv = new ModelAndView("user/user-list", model.asMap());
return mv;
} else {
model.addAttribute("loginForm", new LoginForm());
return new ModelAndView("/login/login-form", model.asMap());
}
}
I thought the #RequestParam(name = "q") and name="q" in html would do the job, but I always get Optional.empty for email. Any idea what's wrong here?
UPDATE:
From the answers I changed controller to this:
#GetMapping("login")
public ModelAndView login(Model model, LoginForm loginForm) {
Optional<UserDto> aUser;
if (loginForm.getEmail() != null) {
aUser = userService.getAUserByEmail(loginForm.getEmail());
model.addAttribute("user", aUser);
var mv = new ModelAndView("user/user-list", model.asMap());
return mv;
} else {
model.addAttribute("loginForm", new LoginForm());
return new ModelAndView("/login/login-form", model.asMap());
}
}
login-form.html to this:
<form th:action="#{/login}" method="get" th:object="${loginForm}" style="max-width: 600px; margin: 0 auto;">
<div class="m-3">
<div class="form-group row">
<label class="col-4 col-form-label">E-mail: </label>
<div class="col-8">
<input type="text" th:field="*{email}" class="form-control" required />
</div>
</div>
<div class="form-group row">
<label class="col-4 col-form-label">Password: </label>
<div class="col-8">
<input type="password" th:field="*{password}" class="form-control" required/>
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">Log in</button>
</div>
</div>
</form>
I also have LoginForm.java like this
#Data
#AllArgsConstructor
#NoArgsConstructor
public class LoginForm {
private String email;
private String password;
}
but still not getting user email field input?
The way you have set up your form, it's mapping the value of your email input field to the property email (that's what th:field="*{email}" means) of an object called loginForm (that's what th:object="${loginForm}" means). Neither of these seem to be used or even exist in your login() method. You need to either change what you use in your controller to match what you have in your Thymeleaf template, or change your Thymeleaf template to actually reference what you are using in your controller.
The problem in your code is located under th:object="${loginForm}"
With this you inform spring to bind the data sent from the form into an object named loginForm.
So Spring actually expects the controller to be
#GetMapping("login")
public ModelAndView login(Model model, LoginForm loginForm) {
....
and inside LoginForm a field named email will contain the value sent from the form, as you have declared with <input type="text" th:field="*{email}" .... >
If you don't want the data to be bound into an object from Spring Mvc then
remove the th:object="${loginForm}"
use the
<input type="text" th:name="q" class="form-control" required />
and then the controller will receive the sent value as a query parameter
#GetMapping("login")
public ModelAndView login(Model model, #RequestParam(name =
"q", required = false) Optional<String> email) {

Why my form data are not intercepted in my mainController in Java Intellij

I get an Internal Server Error, status=500: java.lang.NumberFormatException
The reason seems to be that my form data, sent via name attribute is not intercepted by #RequestMapping or HttpServletRequest doesn't work..
Here I try to pass the data:
<form action="/tankbeurt" method="get" style="padding: 5px;">
<div style="padding: 10px;">
<label for="huidig">Huidige kilometerstand</label>
<input type="text" name="huidig" id="huidig"></div>
<div style="padding: 10px;">
<label for="vorig">Vorige kilometerstand</label>
<input type="text" name="vorig" id="vorig"></div>
<div style="padding: 10px;">
<label for="liter">Hoeveel liter heb je bijgetankt</label>
<input type="text" name="liter" id="liter"></div>
<div><input type="submit" value="Bereken Verbruik"></div>
And I try to intercept it in the mainController:
#Controller
public class MainController {
#RequestMapping("/tankbeurt")
public String gegevens(HttpServletRequest request, Model model){
int huidigeKm = Integer.parseInt("huidig");
System.out.println(huidigeKm);
int vorigeKm= Integer.parseInt("vorig");
double liter= Double.parseDouble("liter");
Tankbeurt tankinformatie = new Tankbeurt(vorigeKm,huidigeKm,liter);
model.addAttribute("informatieTanken",tankinformatie);
return "tankbeurt";
}
Thankyou for your help. I don't see the problem.
Integer.parseInt("huidig");
You are trying to parse string "huidig" to integer. That's the cause of exception. Try looking for some method that extracts property from the model, like "model.getAttribute("huidig")".

Missing parameter error when submitting a form with two request params

Below is code from a controller that I'm aiming to make sure it's receiving two input parameters (name and code) from a front-end interface.
It's a page that takes two parameters within a submit form, "name" and "code".
#RequestMapping(method = RequestMethod.POST)
public String transfer(#RequestParam(name = "name") String name,
#RequestParam(name = "code") String code,
Errors errors, RedirectAttributes redirectAttributes) {
try {
User userToBeTransferred = usersRepository.findByName(name);
userToBeTransferred.setTransferred(true);
Region regionOfTransference = regionsRepository.findByCode(code);
regionOfTransference.setPopulationNumber(regionOfTransference.getPopulationNumber() + 1);
userToBeTransferred.setRegion(regionOfTransference);
usersRepository.save(userToBeTransferred);
regionsRepository.save(regionOfTransference);
return "redirect:/section/users/new";
} catch (IllegalArgumentException e) {
return "htmlPageOne";
}
}
The front-page form :
<form class="form-horizontal" method="POST" action="/section/users/new" th:object="${user}">
<input type="hidden" th:field="*{id}"/>
<div class="form-group row">
<label for="name" class="col-form-label">User name</label>
<input type="text" class="form-control" id="name" th:field="*{name}" name="name"/></div>
<div class="form-group row">
<label for="code" class="col-form-label">Code</label>
<input type="text" class="form-control" id="code" th:field="*{region.code}" name="code"/></div>
<button type="submit" class="btn btn-primary col-sm-6 ">Save</button>
</form>
For some reason, I'm getting the following error after I click to submit the form :
There was an unexpected error (type=Bad Request, status=400).
Required String parameter 'code' is not present
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'code' is not present
I'm not sure if I'm using the requestparams correctly, so maybe it's got something to do with this? I don't know, I've been stuck on this for a few hours now, so would appreciate if someone could help me.
The problem is that th:field="*{region.code}" overrides your name attribute into name="region.code". You can tell by inspecting the rendered <input> element using dev tools of your browser.
You can change following
th:field="*{region.code}"
...into:
th:value="${user.region.code}"

Spring MVC + Thymeleaf Post Single Object to Controller

I'm sort-of shocked that I can't find an example of how to do this. Every time I google it, I get info on how to post a collection of objects, or other unrelated stuff. The thymeleaf documentation (what I can find of it) seems to not explain much either, like there is a lot of assumed knowledge.
Getting back to my question, I just want to post a single object (bean) from a form. I would like my controller mapping method to bind to this "pojo" bean and not to a bunch of strings/integers.
The only thing that I have found that comes close is stuff on StackOverflow where half of the code is in the question, the other half is in the answer, and there are always a few comments from people saying it didn't work for them.
Can anyone offer any relief here with a plain old boring example?
Can find the below code snippet might helpful for you.
Controller GET/POST mapping:
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registartionPage(Model model) {
Registration registration = new Registration();
model.addAttribute("registration", registration);
return "registarion/registarion";
}
#RequestMapping(value = "/user/new-user-registrn", method = RequestMethod.POST)
public String newUserRegistrn(Model model, #ModelAttribute("registration")
Registration registration, RedirectAttributes redirectAttributes) {
try {
StarUser user = starSecurityService.findSysUserName(registration.getUserName());
if (user != null) {
throw new Exception("User Already Exist. Please try with different User Name");
}
user = (StarUser) starUtilService.save(setStarUser(registration));
model.addAttribute("registration", registration);
if (user != null) {
redirectAttributes.addAttribute("starMessage",
"Your Account is successfully created !! Login to Access the Application");
return "redirect:/";
}
} catch (Exception e) {
model.addAttribute(STAR_MESSAGE, e.getMessage());
}
return "registarion/registarion";
}
Thymeleaf Content:
<form class="form-horizontal col-sm-12" method="POST" th:action="#{/user/new-user-registrn}" th:object="${registration}">
<div class="row">
<div class="form-group col-md-12">
<div class="star-reg-header">New User Registration</div>
</div>
<div class="star-reg-body">
<div class="form-group col-sm-4">
<label class="required">First Name: </label>
<input type="text" class="form-control required" th:field="*{firstName}" required="required" />
</div>
<div class="form-group col-sm-4">
<label class="required">Last Name: </label>
<input type="text" class="form-control" th:field="*{lastName}" required="required" />
</div>
<div class="form-group col-sm-4">
<label class="required">User Name: </label>
<input type="text" class="form-control" th:field="*{userName}" required="required" />
</div>
<div class="form-group col-sm-4">
<label class="required">Password: </label>
<input type="password" class="form-control" th:field="*{password}" required="required" />
</div>
<div class="form-group col-sm-4">
<label class="required">Email: </label>
<input type="text" class="form-control" th:field="*{email}" required="required" />
</div>
</div>
</div>
<div class="form-group col-md-12">
<label class="col-sm-2"></label>
<div class="col-sm-10">
<button type="submit" class="btn btn-info">Submit</button>
</div>
</div>
Java Bean class
public class Registration {
protected String firstName;
protected String lastName;
protected String userName;
protected String password;
protected String email;
//Setter and Getter
}
Use #ModelAttribute annotation in the parameter.
Something like this.
#RequestMapping(value = "/someurl", method = RequestMethod.POST)
public String savePojo(#ModelAttribute PojoClass pojo, Model model) {
//Code
}
Edit: This answer has very good info on this.
What is #ModelAttribute in Spring MVC?

Spring submit form get checkbox value not working

I cannot get "remember-me" checkbox value (getting 400 Required boolean parameter 'remember' is not present)
Trying to user #RequestParam. (as for inputs email/password).
How to get checkbox value and not 400 error?
Controller
#RequestMapping(value = "/login", method = RequestMethod.POST)
private String doLogin(#RequestParam(value = "inputEmail") String inputEmail,
#RequestParam(value = "inputPassword") String inputPassword,
#RequestParam(value = "remember") boolean remember,
HttpSession session) {
HTML form
<form class="form-login" method="post" action="/login">
<h2 class="form-login-heading">Please log in</h2>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="inputEmail" class="form-control" placeholder="Email address" required
autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="inputPassword" class="form-control" placeholder="Password" required>
<div class="checkbox">
<label>
<input type="checkbox" name="remember" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block btn-login" type="submit">Log in</button>
</form>
Please remove value="remember-me" from your check box.
When you will tick checkbox spring will map string value "remember-me" with Boolean which is not possible as i know.

Categories