Saving model state using Post / Redirect / Get pattern

I'm currently trying to implement the Post / Redirect / Get pattern using Spring MVC 3.1. What is the correct way to save and restore model data + validation errors? I know that I can save the model and BindingResult using RedirectAttributes in the POST method. But what is the correct way to recover them in the GET method from the flash area?

I did the following for POST:

@RequestMapping(value = "/user/create", method = RequestMethod.POST) public String doCreate(@ModelAttribute("user") @Valid User user, BindingResult result, RedirectAttributes rA){ if(result.hasErrors()){ rA.addFlashAttribute("result", result); rA.addFlashAttribute("user", user); return "redirect:/user"; } return "redirect:/user/success"; } 

And to get the user creation form:

  @RequestMapping(value = "/user", method = RequestMethod.GET) public ModelAndView showUserForm(@ModelAttribute("user") User user, ModelAndView model){ model.addObject("user", user); model.setViewName("userForm"); return model; } 

This allows me to save user data in case of an error. But what is the correct way to recover errors? (BindingResult) I would like to show them in a form with Spring form tags:

 <form:errors path="*" /> 

Also, it would be interesting how to access the flash area from the get method?

+6
source share
3 answers
 public class BindingHandlerInterceptor extends HandlerInterceptorAdapter { public static final String BINDING_RESULT_FLUSH_ATTRIBUTE_KEY = BindingHandlerInterceptor.class.getName() + ".flashBindingResult"; private static final String METHOD_GET = "GET"; private static final String METHOD_POST = "POST"; @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if(METHOD_POST.equals(request.getMethod())) { BindingResult bindingResult = getBindingResult(modelAndView); FlashMap outFlash = RequestContextUtils.getOutputFlashMap(request); if(bindingResult == null || ! bindingResult.hasErrors() || outFlash == null ) { return; } outFlash.put(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY, bindingResult); } Map<String, ?> inFlash = RequestContextUtils.getInputFlashMap(request); if(METHOD_GET.equals(request.getMethod()) && inFlash != null && inFlash.containsKey(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY)) { BindingResult flashBindingResult = (BindingResult)inFlash.get(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY); if(flashBindingResult != null) { BindingResult bindingResult = getBindingResult(modelAndView); if(bindingResult == null) { return; } bindingResult.addAllErrors(flashBindingResult); } } } public static BindingResult getBindingResult(ModelAndView modelAndView) { if(modelAndView == null) { return null; } for (Entry<String,?> key : modelAndView.getModel().entrySet()) { if(key.getKey().startsWith(BindingResult.MODEL_KEY_PREFIX)) { return (BindingResult)key.getValue(); } } return null; } } 
+3
source

Why don’t you show the update form after the binding fails, so the user may try to resubmit the form?

The standard approach for this seems to be to return the form of the update form from the POST handler method.

 if (bindingResult.hasErrors()) { uiModel.addAttribute("user", user); return "user/create"; } 

You can then display errors with the form: errors tag.

+1
source

What is the correct way to restore them in a GET method from flash scope

I'm not sure I understand what you mean by restoring them. What you add as attributes of flash memory before redirection will be in the model after redirection. There is nothing special for this. It sounds like you're trying to ask something else, but I'm not sure what it is.

As Fan remarked, why are you redirecting the error? A common way to handle this is to redirect to success.

0
source

Source: https://habr.com/ru/post/908709/


All Articles