this method opens a page when clicking on a link in which I want the value of the message attribute, I did not add the servlet and jsp, how can I display it? my html is empty
#GetMapping("/activate/{code}")
public String activate(ModelMap model, #PathVariable String code) {
boolean isActivated = userService.activateUser(code);
if (isActivated) {
model.addAttribute("message", "User Successfully activated");
System.out.println("Successfully");
} else System.out.println("Activation code not found");
model.addAttribute("message", "Activation code not found");
return "verificationPage";
}
try to use RedirectAttributes
#GetMapping("/activate/{code}")
public String activate(ModelMap model, #PathVariable String code, RedirectAttributes redirAttrs) {
redirAttrs.addFlashAttribute("message", "Here is your message");
}
Related
In a Spring-Boot controller during user registration if there is a binding error my controller returns the user to the registration page but in my implementation the model seems to be missing.
For example I commonly see on tutorials
#PostMapping
public String registerUserAccount(#ModelAttribute("user") #Valid UserRegistrationDto userDto,
BindingResult result){
User existing = userService.findByEmail(userDto.getEmail());
if (existing != null){
result.rejectValue("email", null, "There is already an account registered with that email");
}
if (result.hasErrors()){
return "registration";
}
userService.save(userDto);
return "redirect:/registration?success";
}
Which, if there are binding errors returns "registration"
My controller is very similar:
#PostMapping("/user/register")
public String registerNewUser(#ModelAttribute("user") #Valid RegisterUserDTO registerUserDTO,
BindingResult bindingResult,
Model model,
HttpServletRequest request,
Errors errors) {
User existing = userService.findUserByEmail(registerUserDTO.getEmail());
if (existing != null) {
bindingResult.rejectValue("email", null, "There is already an account with that Email");
}
if (bindingResult.hasErrors()) {
return "register";
}
userService.createUser(registerUserDTO);
return "redirect:/registration?success";
}
}
However when I return "register" there is a binding error on the stack at what corresponds to my first thymeleaf tag relating to the object.
If I change the POST controller to add the model explicitly:
if (bindingResult.hasErrors()) {
model.addAttribute(registerUserDTO);
return "register";
}
Then it works, returning the page with the model and previously entered data.
Why am I having to explicitly add the model to the return?
UPDATE
This does not work either:
#PostMapping("/user/register")
public String registerNewUser(#ModelAttribute("user") #Valid RegisterUserDTO registerUserDTO,
BindingResult bindingResult) {
User existing = userService.findUserByEmail(registerUserDTO.getEmail());
if (existing != null) {
bindingResult.rejectValue("email", null, "There is already an account with that Email");
}
if (bindingResult.hasErrors()) {
return "register";
This worked:
#PostMapping("/user/register")
public String registerNewUser(#ModelAttribute("registerUserDTO") #Valid RegisterUserDTO registerUserDTO,
BindingResult bindingResult) {
User existing = userService.findUserByEmail(registerUserDTO.getEmail());
if (existing != null) {
bindingResult.rejectValue("email", null, "There is already an account with that Email");
}
if (bindingResult.hasErrors()) {
return "register";
}
userService.createUser(registerUserDTO);
return "redirect:/registration?success";
}
As M.Denium pointed out the #ModelAttribute name needed to be the same as the instance name of the backing object used in the GET controller. In my GET controller I had :
#GetMapping("/user/register")
String registerForm(Model model) {
RegisterUserDTO registerUserDTO = new RegisterUserDTO();
model.addAttribute(registerUserDTO);
return "register";
}
So the #ModelAttribute needs to match, ie #ModelAttribute("registerUserDTO")
I have this POST method which only validates a form and returns a confirmation view if the form is validated and I want to send back to the register screen if any field is wrong. In this case if the BindingResult object has errors, the system send the user back to the form screen but the URL shown is "/registerConfirmation" which should only be in case the form has no errors.
#RequestMapping(value="/registerConfirmation", method = RequestMethod.POST)
public ModelAndView confirmRegister(#Valid #ModelAttribute("form") RegistrationForm form, BindingResult result){
logger.info("Sending registration data");
ModelAndView modelAndView = new ModelAndView();
if(result.hasErrors()){
modelAndView.setViewName("register");
modelAndView.addObject("form", form);
return modelAndView;
}
//more code here
return modelAndView;
}
I dont know what I'm missing as I have seen methods like this in many other posts. Any help??
Many thanks!!!
One way to solve your issue is to use redirect:
#RequestMapping(value="/registerConfirmation", method = RequestMethod.POST)
public String confirmRegister(#Valid #ModelAttribute("form") RegistrationForm form, BindingResult result, RedirectAttributes attr){
logger.info("Sending registration data");
if(result.hasErrors()){
attr.addFlashAttribute("org.springframework.validation.BindingResult.form", result);
attr.addFlashAttribute("form", form);
return "redirect:/register";
}
//more code here
return "redirect:/registerConfirmation";
}
and in your register GET method you should check:
#RequestMapping(value="/register", method = RequestMethod.GET)
public String showRegister(Model model) {
....
if (!model.containsAttribute("form")) {
model.addAttribute("form", new RegistrationForm());
}
.....
}
you can read more in this article
Also don't forget to create GET method with registerConfirmation value.
I have the following controller code redirecting to a page:
#RequestMapping(value="/site_form", method = RequestMethod.POST)
public String welcomeForm(ModelMap model, #Valid #ModelAttribute Site s,
BindingResult br, RedirectAttributes ra) {
if (br.hasErrors()) {
model.addAttribute("errors", br.getAllErrors());
return "hello";
}
model.addAttribute("message", "Entry Log");
model.addAttribute("site", s);
ra.addAttribute("flash", "Site saved successfully");
return "redirect:/app/admin/site_form";
I'm trying to access ${flash} in the controller, but cannot.
Also, I though this was supposed to go in the session, but my URL after the redirect URL hit as a get attribute.
I'm stuck.
It has to be ra.addFlashAttribute("flash", "...").
I have this piece of code:
#RequestMapping(value="login/authUser", method=RequestMethod.POST)
public String authUser(#RequestParam("login") String login,
#RequestParam("password") String password, ModelMap model){
(...)
if (password.equals(user.getPassword())){
ModelMap modelMap = new ModelMap();
modelMap.put("loggedUser", user.getName() + " " + user.getSurname());
return "home";
}
else{
model.put("info", "Bad data!");
return "index";
}
For bad password, everything is correct - it returns a with information "bad data", but if password is correct I can't get an info about logged user (but it redirects correctly). Because ModelMap model is ,,bind" to index.jsp it works when it redirects to index jsp, but is there a way to "bind" new ModelMap to view called home.jsp with simply way or I have to use ModelAndView?
Thank you in advance.
#SOLVED: It was my stupidity, I simple do not initialize name and surname in variable user, and because of it there were a "" instead name and surname which I want to see in home.jsp. Now, with user with name and surname set it works great :)
LoginFormController-->Post is invoked after the form is submitted/posted. At the end, it invokes another Controller called LandingFormController-->loadForm.
Well, in the loadForm the values in the Model seems to be empty. Is there a way I can persist a Bean in session or request and get it in the loadForm method? Bonus points: if you could point to some documents to refer :)
Thanks
#Controller
#RequestMapping(value="/login")
public class LoginFormController {
#RequestMapping(method=RequestMethod.POST)
public ModelAndView post(#ModelAttribute User user, BindingResult result, SessionStatus status) {
logger.info("post");
new ReceiptUserValidator().validate(user, result);
if (result.hasErrors()) {
return new ModelAndView("login");
}
else {
logger.info("Email Id: " + user.getEmailId());
//status.setComplete();
Map<String, Object> model = new HashMap<String, Object>();
model.put("userId", user.getEmailId());
model.put("now", new Date().toString());
return new ModelAndView("redirect:/landing.htm", "model", model);
}
}
Controller B below that gets called
#Controller
#RequestMapping(value="/landing")
public class LandingFormController {
protected final Log logger = LogFactory.getLog(getClass());
#RequestMapping(method=RequestMethod.GET)
public String loadForm(Model model) {
logger.info("LandingFormController loadForm: " + model.asMap().keySet());
return "landing";
}
}
The code is performing a redirect which causes the properties placed in the model to be lost. Use flash attributes to pass the attributes to the next controller.
Flash attributes provide a way for one request to store attributes
intended for use in another. This is most commonly needed when
redirecting — for example, the Post/Redirect/Get pattern. Flash
attributes are saved temporarily before the redirect (typically in the
session) to be made available to the request after the redirect and
removed immediately.
LoginFormController
#Controller
#RequestMapping(value="/login")
public class LoginFormController {
#RequestMapping(method=RequestMethod.POST)
public ModelAndView post(#ModelAttribute User user, BindingResult result,
SessionStatus status, final RedirectAttributes redirectAttrs) {
logger.info("post");
new ReceiptUserValidator().validate(user, result);
if (result.hasErrors()) {
return new ModelAndView("login");
}
else {
logger.info("Email Id: " + user.getEmailId());
//status.setComplete();
redirectAttrs.addFlashAttribute("userId", user.getEmailId());
redirectAttrs.addFlashAttribute("now", new Date().toString());
return new ModelAndView("redirect:/landing.htm", "model", model);
}
}
Documentation
As an alternative solution you could simply not perform a redirect from the controller.
Appending retrieving solution.
Modify the loadForm
public String loadForm(#ModelAttribute("user") User user) {
logger.info("LandingFormController loadForm: " + user.getEmailId());
return "landing";
}