A simple solution with Sping MVC to print info messages to the user after a redirect is RedirectAttribute. They will only show up a single time after a redirect. Spring initializes RedirectAttribute in the method param.
Example for setting a flash attribute:
|
1 2 3 4 5 6 7 8 9 10 11 |
@RequestMapping(value = "/create", method = RequestMethod.POST) public String create(@ModelAttribute("market") Market market, BindingResult result, SessionStatus status, final RedirectAttributes redirectAttributes) { validator.validate(market, result); if (result.hasErrors()) { return CREATE_JSP; } // ... save ... status.setComplete(); redirectAttributes.addFlashAttribute("message", "admin.message.saved"); return String.format("redirect:/admin/market/view?id=%s", market.getId()); } |
and display it with the following code in your view
|
1 2 3 |
<c:if test="${message != null}"> <div class="infoMsg"><spring:message code="${message}" /></div> </c:if> |
Testing it
The messages are attached as an attribute in the request so they can be easily tested in a unit test:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Test public void testCreateSuccess() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(RequestMethod.POST.name(), "/admin/market/create"); request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.addParameter("name", "ZZ"); MockHttpServletResponse response = new MockHttpServletResponse(); Object handler = handlerMapping.getHandler(request).getHandler(); ModelAndView modelAndView = handlerAdapter.handle(request, response, handler); BindingResult bindingResult = (BindingResult) modelAndView.getModel().get(String.format("%s.%s", BindingResult.class.getName(), "market")); assertTrue("Should have no errors", bindingResult == null || !bindingResult.hasErrors()); assertFlashAttributeNotNull("Should contain success message", request, "message"); assertTrue(modelAndView.getViewName().startsWith("redirect:/admin/market/view?id=")); } static public void assertFlashAttributeNotNull(String message, ServletRequest request, String name) { FlashMap flashMap = (FlashMap)request.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE); assertNotNull(message, flashMap.get(name)); } |
One thing is a bit wired. If spring initialize RedirectAttributes in the method and there are no errors in the BindingResult, it “feels” like there is some kind of redirect simulation. The ModelMap is empty after that and BindingResult is null. Without RedirectAttributes the BindingResult remains without errors in the model map. I think it’s more realistic with an empty ModelMap after the redirect, but I can’t understand why the behaviour is different?