Spring-Boot: Redirect and Refresh model and page

2017-10-12 spring spring-mvc redirect thymeleaf

I have a spring-boot application, with theyemleaf. I repeatedly update the page, and redirect it to the same page, so i expect that the elements of the page get updated:

@GetMapping("/suggested-events/vote/{eventId}")         
public String voteForEvents(Model model,
                            @PathVariable("eventId") Long eventId,
                            @RequestParam(value = "message", required = false) String message ) {
    log.info("The message is: "+message);
    SuggestedEvent event = suggestedEventService.findSuggestedEventById(eventId);
    ArrayList<SuggestedEvent> events = suggestedEventService.findSuggestedEventsByArea(event.getArea());
    model.addAttribute("mainEvent",event);
    model.addAttribute("events",events);
    model.addAttribute("message",message);

    return "/suggested-event/vote";
}

and when a button get pushed in the view it triggers the below post method:

@PostMapping("/suggested-events/vote")
public String voteForASuggestedEvent(RedirectAttributes redirectAttributes){
    log.info("You have made a vote");
    redirectAttributes.addAttribute("message", "Success");

    return "redirect:/suggested-events/vote/1";
}

This second controller method, performs an operation an makes a message, and redirects it to the first method. So, it successfully redirected to the first method and it logs

log.info("The message is: "+message);

but it does not refresh my page, and i do not get the message as model?

When i redirect to the first method, i expect it adds the message to my models:

model.addAttribute("message",message);

But it does not added to my page

Answers

there are many ways to redirect page in Spring, but be sure if the model attribute off message its passing correctly to FrontEnd or passing like parameter to another handler , you can see this document : http://javainsimpleway.com/spring-mvc-redirecting-model-attributes-from-one-controller-to-other-controller/ , hope this is useful !!

and when a button get pushed in the view it triggers the below post method:

It sounds like this trigger is using AJAX, rather than a form submit. Doing so would match the symptoms you describe.

If you POST to /suggested-events/vote using AJAX, the server will return a 302, and the browser will follow it. However, the response for that 302 is still the result of an AJAX call. You have access to it in your success callback, but the browser isn't going to render it for you.

but it does not refresh my page

If a 302 doesn't cause your page to re-render, this also suggests you're using AJAX.

If you actually use a form submit instead, the browser will re-render using the markup returned by the successful redirect.

This can be verified by using the following two buttons in your vote.html:

  <form action="http://localhost:8080/suggested-events/vote" method="POST">
    <input type="submit" text="Submit" />
  </form>

  <button onclick="postmessage();" >Button</button>

  <script>
    function postmessage() {
        $.ajax({
            method: 'POST',
            data: {},
            url: 'http://localhost:8080/suggested-events/vote'
        });
    }
  </script>

The first button will work as expected, and the second button matches the symptoms you describe.

If you are already using a form, please update the question with it (or better yet, the entire Thymeleaf template).

I had the same problem as OP described and Mike's explanation brought me in the right direction.

I am reading a db-table and populating it with thymeleaf using th:each. I wanted to add a javascript-confirmation before deleting an item. Sending an ajax GET without an event-listener and reloading with location.reload(true) didn't reach the @GetMapping("/delete/{id}") in the controller.

This SO-thread gave me the answer to the ajax-call.

<a class="btn btn-danger" href="#" th:onclick="|confirmDeletion('${u.id}')|"></a>

<script th:inline="javascript">
    function confirmDeletion(id) {
        if (confirm("Delete this id? " + id)) {
            var http = new XMLHttpRequest();
            http.open("GET", "/delete/" + id, true);
            http.addEventListener("readystatechange", function() {
                if (http.readyState === 4 && http.status === 200) {
                    window.location.reload(true);
                }
            });
            http.send();
        }
    }
</script>

Related