19

I downloaded the code for the Spring MVC 3 Showcase. One thing puzzles me (well, more than one), why does this (edited for concision) sample return null?

@Controller
@RequestMapping("/form")
public class FormController {
    @RequestMapping(method=RequestMethod.POST)
    public String processSubmit(@Valid FormBean form, 
                BindingResult result, 
                WebRequest webRequest, 
                HttpSession session, Model model) {

        if (result.hasErrors()) {
             return null;
        } else {
            session.setAttribute("form", form);
            return "redirect:/form";            
        }
    }
}
Paul McKenzie
  • 19,646
  • 25
  • 76
  • 120

2 Answers2

27

If a controller returns a null view name, or declares a void return type, Spring will attempt to infer the view name from the request URL.

In your case, it will assume the view name is form, and proceed on that assumption.

It does this using an implementation of RequestToViewNameTranslator, the default implementation of which is DefaultRequestToViewNameTranslator, the javadoc for which explains the exact rules it applies.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Does a RequestToViewNameTranslator bean have to be explicitly provided, or does Spring provide this out of the box? – acvcu Feb 28 '14 at 21:14
4

AnnotationMethodHandlerAdapter.invokeHandlerMethod() takes care of invoking handler methods. Here, a ModelAndView will be retrieved via ServletHandlerMethodInvoker.getModelAndView().

In your case, getModelAndView() gets provided the handler method's null return value. The getModelAndView() method checks for the return value's type, but as in Java null is never an instanceof any class, that method's logic will create a new ModelAndView. A new ModelAndView has initially its view property set to null.

Then later back up the call stack, in DispatcherServlet.doDispatch(), there is a test if the ModelAndView object has a View associated with it ( mv.hasView() ). Because view == null, doDispatch()'s logic calls mv.setViewName(getDefaultViewName(request)). It delegates to the registered RequestToViewNameTranslator, whose default implementation is DefaultRequestToViewNameTranslator. This subclass translates the request URI into a view name, in your case form.

Later in doDispatch(), via render() -> resolveViewName(), this sample's ViewResolvers are provided with the view name form. Only one ViewResolver, InternalResourceViewResolver is used in this sample. Also, this InternalResourceViewResolver was configured in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml to add the prefix /WEB-INF/views/ and the suffix .jsp to the view name. So in total, it will create a View using the JSP file /WEB-INF/views/form.jsp. Luckily, a JSP file exists at exactly this location.

Community
  • 1
  • 1
Abdull
  • 26,371
  • 26
  • 130
  • 172