0

I have a thymeleaf signup form, which if we submit then a controller at "/signup_do" is called which validates and saves the user to database:

<form action="/signup_do" method="post">
    ...
</form>

The controller at "/signup_do" passes the request to the accountRegistration service method, which does the validation:

@PostMapping("/signup_do")
public String register(Account account, HttpSession session) {

    session.setAttribute("accountToRegister", account);
    accountManagement.accountRegistration(account);

    return "Success";
}

The account registration method can throw an exception SignupFormException, which is handled by the @ExceptionHandler defined in that controller class:

@ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, Model response) {

    Account returnDataToForm = (Account) session.getAttribute("accountToRegister");
    response.addAttribute("name", returnDataToForm.getFirstName());
    session.invalidate();

    return "signup";
}

Now the problem is that when exception occurs, the inputs entered in the form is passed back to the signup form, and the entered data remains intact, but the url still remains as /signup_do.

I have tried using return "redirect:/signup" instead, which does change the url, but it ends up making a get request to the /signup url like

/signup?name=John...

but my /signup controller is not designed to handle a get request, it just knows to display the form, so the information is lost.

@GetMapping("/signup")
public String signupPage() {return "signup";}

I also tried using forward:/signup, but that just ended up throwing 405 error.

YeetCoder
  • 304
  • 1
  • 3
  • 12

2 Answers2

1

I figured out a clean workaround a few hours after asking this question.

What I did is change the name of the controller that handles the signup process to ("/signup") as well. Since the controller that displays the page is a @GetMapping("/signup") and the one that handles the signup process is a @PostMapping("/signup") there is no clash.

Now even if the controller changes, the url remains the same, since both of them are signup...

@GetMapping("/signup")
public String signupPage() {return "signup";}

@PostMapping("/signup")
public String register(Account account, HttpSession session) {

    session.setAttribute("accountToRegister", account);
    accountManagement.accountRegistration(account);

    return "success";
}

And this works just like I wanted!!

YeetCoder
  • 304
  • 1
  • 3
  • 12
0

Redirecting will make a get request to the controller looking for the view to display, which in your situation means losing your data for the reasons you give. I can think of two workarounds:

  1. Don't do the redirect and change the URL manually with javascript everytime you enter this view. If you dislike having a "wrong" URL in a view, editing it manually looks the most reasonable and direct approach. You can see how to do this here, including it in a script that executes everytime the page loads/the submit button is pressed.

  2. Do the redirect and avoid losing your info by storing it in the session for a while longer, accessing it in thymeleaf in this way, instead of getting it from a model attribute. This would mean you would have to be careful to remove this session attributes later. It's also not very "clean" that your get request for the form view includes the user info, so I wouldn't go with this solution if avoidable.

Jorge.V
  • 1,329
  • 1
  • 13
  • 19