0

I am trying to create a custom error message in my controller and then pass it into the HTML template if the email is already found in the database.

The controller method does work and it will redirect the user to "registration-form" if a duplicate email is used, but the error message is not displayed on the web page as I intend it to be.

I basically want the error message to appear on the screen when the user cannot register with that email.

In HTML form:

<p th:text="*{errorMessage}"></p>

In Controller:

    @PostMapping("/process-register")
    private String processRegistrationForm(Model model, WebUser webUser) {
        String email = webUser.getEmail();

        if(webUserRepo.findByEmail(email) == null) {
            webUser.setRole("user");
            WebUser savedWebuser = webUserRepo.save(webUser);
            model.addAttribute("userID", savedWebuser.getUserID());
            String userID = String.valueOf(savedWebuser.getUserID());
            return "redirect:/welcome/" + userID;
        }
        else {
            String errorMessage = "This email address is already registered, please login to your existing account.";
            model.addAttribute(errorMessage);
            return "registration-form";
        }

    }
}
devo9191
  • 219
  • 3
  • 13

1 Answers1

1

When your original request is not cached (i.e. is a POST, DELETE, PUT, ... operation) you can respond with any MVC flow, simply be sure to not use the path for "weird" things (neither server nor client side).

Then, if the email exists put the message into the model and redirect to the remember password (or login ...).

So, you can prepare your RememberController to be called from others controllers decoupling internal state and logic:

@Controller
@RequestMapping("/remember")
public class RememberController {

    @Getter
    @Setter
    @AllArgsConstructor
    public static class RememberModel {
        private String email;
    }

    // this method decouple the RememberController knowledge (i.e. merge, remove, get messages, ... needed by this view)
    public String redirect(Model model, String email) {
        model.addAttribute("form", new RememberModel(email));
        return get(model);
    }

    @GetMapping
    public String get(Model model) {
        if (model.getAttribute("form") == null)
            model.addAttribute("form", new RememberModel(""));
        return "remember";
    }

    @PostMapping
    public String post(@ModelAttribute(name = "form") RememberModel form, Model model) {
        model.addAttribute("info", "password sent to " + form.getEmail() + "!");
        return "remember";
    }

}

Now, your RegisterController can redirect with any required information (i.e. the error message and the user email to not to rewrite twice):

@Controller
@RequestMapping("/register")
public class RegisterController {

    @Getter
    @Setter
    @AllArgsConstructor
    public static class RegisterModel {
        private String email;
    }

    @Autowired
    protected RememberController rememberController;

    @GetMapping
    public String get(Model model) {
        if(model.getAttribute("form") == null)
            model.addAttribute("form", new RegisterModel(""));
        return "register";
    }

    @PostMapping
    public String post(@ModelAttribute(name = "form") RegisterModel form, Model model) {
        // ... when email exists ...
        model.addAttribute("error", "e-mail `" + form.getEmail() + "` exists!");
        return rememberController.redirect(model, form.getEmail());
    }
}

Then, the user UI works as expected:

GET

GET register

POST and server redirecto to remember controller

POST and redirect

Then user simply click:

POST remember

The views are:

<!doctype html>
<html th:attr="lang=en" xmlns:th="http://www.w3.org/1999/xhtml">
<body>
<h1>REGISTER FORM</h1>
<div style="color: red" th:if="${error != null}" th:text="${error}"></div>
<div style="color: green" th:if="${info != null}" th:text="${info}"></div>
<form method="post" th:object="${form}">
    <input th:field="*{email}" type="text"/>
    <input type="submit" value="register"/>
</form>
</body>
</html>

and

<!doctype html>
<html th:attr="lang=en" xmlns:th="http://www.w3.org/1999/xhtml">
<body>
<h1>REMEMBER FORM</h1>
<div style="color: red" th:if="${error != null}" th:text="${error}"></div>
<div style="color: green" th:if="${info != null}" th:text="${info}"></div>
<form method="post" th:action="@{/remember}" th:object="${form}">
    <input th:field="*{email}" type="text"/>
    <input type="submit" value="remember"/>
</form>
</body>
</html>

NOTE: for a better user experience, you can change the url when the remember view is redirected on server using window.history.pushState or so.

josejuan
  • 9,338
  • 24
  • 31