Search code examples
javahtmlspring-bootthymeleafuser-registration

How to keep the data in the form after redirecting back from an exception


I have a signup form in html(Thymeleaf template), and once I submit this form the following controller method is called:

@PostMapping("/signup_do")
public String register(Account account) {
    accountManagement.accountRegistration(account);

    return "Success";
}

Now accountRegistration is a service method which throws SignupFormException, which extends RuntimeException. This exception is handled in the same class as the controller with @ExceptionHandler anotation as follows:

@ExceptionHandler(value=SignupFormException.class)
public String handle() {
    return "redirect:/signup";
}

This returns an empty signup form back on facing an exception. But I want the values that are OK to remain populated.

If I could recieve the account object that was originally passed to the /signup_do controller into this exceptionhandler method, I could easily return model object back. But the following does not work:

@ExceptionHandler(value=SignupFormException.class)
public String handle(Account account) { //trying to get the account object
    System.out.println(account.getUsername());
    return "redirect:/signup";
}

The exception that is thrown is:

java.lang.IllegalStateException: Could not resolve parameter [0] in public java.lang.String tv.redore.controller.AccountController.handle(tv.redore.entity.Account): No suitable resolver

Solution

  • There are many ways to do this, but you can for example store this values in the session, which makes sense since you intent the values to trascend the request into the exception handling.

    1. Store the information in the session when you recieve it in the controller:

      @PostMapping("/signup_do")
      public String register(HttpSession session, Account account) {
          session.setAttribute("account", account);
          accountManagement.accountRegistration(account);
      
          return "Success";
      }
      
    2. Recover the account info in the exception handler and pass it to the model:

      @ExceptionHandler(value=SignupFormException.class)
      public String handle(Model model, HttpServletRequest req) {
          Account account = req.getSession().getAttribute("account");
          req.getSession().removeAttribute("account"); //Important, you don't want to keep useless objects in your session
          model.addAttriute(account.getUsername());
          return "redirect:/signup";
      }
      

    You can even add the exception to the handler:

    public String handle(Model model, HttpServletRequest req)
    

    So that you've more info on what failed, and you know what to do accordingly.