Search code examples
spring-bootthymeleaf

Why @PostMapping doesn't change th:if


I have controller like this:

@Controller
public class AuthController {

private final Logger logger= LoggerFactory.getLogger(AuthController.class);

private UserService userService;

public AuthController(UserService userService) {
    this.userService = userService;
}

@GetMapping("login")
public String login(){
    return "auth/login";
}
@GetMapping("/profile")
public String profile(){
    return "auth/profile";
}
@GetMapping("/register")
public String register(Model model){
    model.addAttribute("user",new User());
    model.addAttribute("success",false);
    return "auth/register";
}
@PostMapping("/register")
public String registerNewUser(@Valid User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes){
    if(bindingResult.hasErrors()){
        //show validation errors
        logger.warn("Validation errors were found while registering a new user");
        model.addAttribute("user",user);
        model.addAttribute("validationErrrs",bindingResult.getAllErrors());
        return "auth/register";
    }else{
        User newUser = userService.register(user);
        redirectAttributes
                .addAttribute("id",newUser.getId())
                .addFlashAttribute("success",true);
        logger.info("No validation errors were found while registerning a new user");
        return "redirect:/register";
    }
}
@GetMapping("/activate/{email}/{activationCode}")
public String activate(@PathVariable String email, @PathVariable String activationCode) {
    Optional<User> user = userService.findByEmailAndActivationCode(email,activationCode);
    if( user.isPresent() ) {
        User newUser = user.get();
        newUser.setEnabled(true);
        newUser.setConfirmPassword(newUser.getPassword());
        userService.save(newUser);
        userService.sendWelcomeEmail(newUser);
        return "auth/activated";
    }
    return "redirect:/";
 }
 }

I call method registerNewUser and all time my logger display info about "No validation errors were found while registerning a new user" because else body is executed. So in my opinion redirectAttributes.addFlashAttribute("success",true); should work correctly. Unfortunately when I return "redirect:/register" I get new view but without allert depend on "succes" atribute. This is part of my view code:

<div class="row" th:if="${success}">
<div class="col-md-3"></div>
<div class="col-md-6 alert alert-success" role="alert" >
    You have successfully registered with us. Please check your email to 
activate your account.
</div>
<div class="col-md-3"></div>
</div>

<!-- User Registration form -->
<form class="form-horizontal" role="form" method="POST" 
th:action="@{/register}" th:object="${user}" th:if="!${success}">
<div class="row">

Somebody can help me pinpoint the cause of the lack of an alert?


Solution

  • Within registerNewUser() you're redirecting to GET /register. This will call the following method:

    @GetMapping("/register")
    public String register(Model model){
        model.addAttribute("user",new User());
        model.addAttribute("success",false);
        return "auth/register";
    }
    

    In this method you're adding a model attribute success and you're setting it to false, effectively overriding the redirect attribute.

    Since RedirectAttributes are used to populate the Model of the redirect target, you could wrap the model.addAttribute(..) call in an if statement. For example:

    @GetMapping("/register")
    public String register(Model model){
        model.addAttribute("user",new User());
        if (!model.containsAttribute("success")) {
            model.addAttribute("success",false);
        }
        return "auth/register";
    }
    

    Alternatively, you could leave the model attribute away, as the parser is smart enough to evaluate ${success} to false when it's missing. For example:

    @GetMapping("/register")
    public String register(Model model){
        model.addAttribute("user",new User());
        return "auth/register";
    }