0

In my Spring Boot application I have an "edit user" form, the form is bound to a SecurityUser bean, but has an additional (non-bean) field for confirming the password. The GET mapping in my controller looks like this:

@GetMapping("/security/user/{username}")
public String showEditUserForm(@PathVariable("username") String username, Model model) {
    model.addAttribute("securityUser",securityUserService.findByUsername(username));
    return "/security/edituser";
}

In the POST mapping, I want to check the password confirmation input's value and compare it to the password field value, so I coded it like this:

@PostMapping("/security/user/{username}")
public String processEditUser(@Valid SecurityUser securityUser, @RequestParam String confirmPassword, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
    if (bindingResult.hasErrors()) {
        return "security/edituser";
    }
    logger.debug(securityUser.toString());
    logger.debug(confirmPassword);

    redirectAttributes.addFlashAttribute("flashstatus","success");
    redirectAttributes.addFlashAttribute("flashmessage","You successfully submitted an edituser form");
    return "redirect:/security/success";
}

If the form is valid, everything works fine (granted, it's just logging and a redirect to a success page). But if any form field is invalid, a 405 error (HTTP method not supported) is the result.

In the logs it's:

2020-02-06 15:44:39.114  WARN 20496 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]

Originally the GET and POST endpoints were different, so I made them the same, as you can see, and that obviously wasn't the solution. If I eliminate the @BindingResult variable from the POST mapping, the bug goes away, but then I obviously can't check the password confirmation.

How can I access a form input that's not a bean field in a Spring Boot POST mapping without this error occurring?

3
  • What happens if you move the BindingResult parameter right after the bean you want to validate, i.e. SecurityUser? Commented Feb 6, 2020 at 21:15
  • That solved it! The method signature is now public String processEditUser(@Valid SecurityUser securityUser, BindingResult bindingResult, @RequestParam String confirmPassword, RedirectAttributes redirectAttributes) {}. But why? How??? Commented Feb 6, 2020 at 21:21
  • @KrisztianToth If you can explain it I'll accept your answer. Commented Feb 6, 2020 at 21:22

1 Answer 1

1

This is one of the rare cases where the order of the argument actually matters. The BindingResult parameter has to be right after the object you want to validate.

From the documentation:

You must declare an Errors, or BindingResult argument immediately after the validated method argument.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.