I have the following GetMapping
handler:
@GetMapping("/auto-upgrade/{id}")
public String followJob(Model model, @PathVariable String id) {
boolean stopMessageAlreadyThere = model.asMap().containsKey("stopMessage");
if (!stopMessageAlreadyThere) {
model.addAttribute("stopMessage", null);
}
//do some stuff
return "dashboard";
}
In the dashboard.html
that I return, I have the following form embedded:
<form action="#" th:action="@{/auto-upgrade/stop}" th:object="${stopRequest}" method="post" th:if="${#strings.toString(upgradeState.upgradeStatus) == 'RUNNING'}">
<input style="visibility: hidden" th:field="*{jobId}" th:value="${upgradeState.id}"/>
<p>Your mail address: <input type="email" id="stoppingEmail" oninput="saveLastInput()" th:field="*{userEmail}"></p>
<p><input type="submit" value="Request stop upgrade" />
</form>
... and then right after I have the following element:
<div th:if="${stopMessage != null}">
<p>Message for stop command: <b th:text="${stopMessage}"></b></p>
</div>
When I render the view, the stopMessage
is null
because it's me inserting it as such.
If I submit the form, I go through this PostMapping
handler:
@PostMapping("/auto-upgrade/stop")
public String stopJob(@ModelAttribute StopRequest stopRequest, Model model) {
try {
//something that may fail
model.addAttribute("stopMessage", "Stop request accepted");
} catch (UpgradeNotRunningException | NotInGracePeriodException | StopUpgradeException e) {
model.addAttribute("stopMessage", "FAILED TO STOP: " + e.getMessage());
}
return "redirect:/auto-upgrade/" + stopRequest.getJobId();
}
So basically I'm always going to add a `stopMessage, whether successful or failing.
However, when I'm called back to my @GetMapping("/auto-upgrade/{id}")
to which I redirect, the Model model
is empty meaning that my value previously saved is not added.
I would have expected Model
to be shared across handlers, but it doesn't look to be the case.
How can I retrieve the value of a property set into another handler? Is it possible with Thymeleaf ?
Note: for the time being, I have made
stopMessage
a field of my Controller class and I set itnull
/ not null around the handlers so that I'm always able to see its value. It is a solution, but it doesn't seem to be the right way to do it. So since I'm new to Thymeleaf, I'd be happy to hear the proper way of handling such cases.
You need to use RedirectAttributes
:
@PostMapping("/auto-upgrade/stop")
public String stopJob(@ModelAttribute StopRequest stopRequest,
Model model,
RedirectAttributes redirectAttributes) {
try {
//something that may fail
redirectAttributes.addFlashAttribute("stopMessage", "Stop request accepted");
} catch (UpgradeNotRunningException | NotInGracePeriodException | StopUpgradeException e) {
redirectAttributes.addFlashAttribute("stopMessage", "FAILED TO STOP: " + e.getMessage());
}
return "redirect:/auto-upgrade/" + stopRequest.getJobId();
}
That way, stopMessage
is available after the redirect. (Note that if the user manually refreshes the page after the redirect, they are lost)
See https://www.baeldung.com/spring-web-flash-attributes for more info.