3

I am trying to understand Spring MVC in more detail what I currently know. I am referring to online tutorials and books. As I understand, Spring MVC framework has "Front controller" and "MVC" design patterns.

The front controller (DispatcherServlet) uses the HandlerMapping for mapping URL to the controller classes. I am not using annotations because I want to understand what the framework does behind the scenes.

In this quest, I created a simple web-application based on Spring MVC, the code is below:

Controller code:

public class SimpleSpringController extends AbstractController {

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse res) throws Exception {

        ModelAndView mw = new ModelAndView("welcome","welcomeMessage", "welcome user!");
        return mw;
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
    <web-app>
        <display-name>FirstSpringMVCProject</display-name>
        <servlet>
            <servlet-name>spring-dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        </servlet>

    <servlet-mapping>
        <servlet-name>spring-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Spring xml configuration

<beans>

    <bean id="HandlerMapping1" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <bean name="/welcome" class="com.example.controller.SimpleSpringController"/>

    <bean id="viewResolver1" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix"> <value>/WEB-INF/</value> </property>
        <property name="suffix"> <value>.jsp</value> </property>
    </bean>

</beans>

The application works as expected.

The concepts which I am not able to understand is on the spring configuration xml where we specify the HandlerMapping and ViewResolver implementations.

For example, we have the following bean definition in the above spring xml configuration:

<bean id="HandlerMapping1" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

In above xml config, org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping is one of the implementations of the HandlerMapping interface.

The bean id for this is HandlerMapping1, which is just a random identifier ( I could have very well chosen MyHandlerMapping). The following are the doubts:

  1. Who reads this configuration file? Do front controller read this configuration file?

  2. How does the framework knows that the id of HandlerMapping implementation in above case is HandlerMapping1. Usually we do getBean("beanId"), where we specifically know what a particular bean id is. How come spring framework is automatically infer that this is the implementation class of HandlerMapping.

Any inputs to understand this would be of great help.

3 Answers 3

3

Initialization

In Spring the front controller is the DispatcherServlet, this extends the FrameworkServlet. The FrameworkServlet by default creates a XmlWebApplicationContext and tries to read an XML file named <servlet-name>-servlet.xml (this is when using a web.xml!). (All this can be overridden by setting the appropriate init-params for the configured DispatcherServlet).

The DispatcherServlet will after loading eventually call the initStrategies method. This method will configure the delegation strategies for the DispatcherServlet. It will first try and detect most of the strategies by type (like HandlerMaping, HandlerAdapter, ViewResolver etc) and some by name (localeResolver, themeResolver, messageSource etc.). If that cannot be found the default strategies for a given interface will be installed. Those defaults are defined in the DispatcherServlet.properties inside Spring.

Important: As soon as you define a strategy yourself the defaults for that strategy don't apply anymore!. For instance if you have a BeanNameUrlHandlerMapping in your configuration, the default configuration for HandlerMapping isn't loaded anymore as you provided explicit configuration.

Request Handling

After startup the DispatcherServlet is ready to handle request.

DispatcherServlet Flow Image comes from the Spring Framework reference guide

Handler Selection and execution

What happens is when a request is handled by the DispatcherServlet it will check all configured HandlerMappings to see if one is able to provide a handler (a Controller or @Controller is just one of the handler types that can be handled) for the given request. As soon as a handler is found, it will lookup a HandlerAdapter for the detect handler. If that is also found the found handler together with the current HttpServletRequest and HttpServletResponse are passed to the HandlerAdapters handle method.

View resolution

Now if a ModelAndView is being returned from the HandlerAdapter.handle method a View is going to be resolved if the ModelAndView.getViewName() method returns a name, this is going to be passed on the an to a ViewResolver to be resolved into a View.

When a View is either being resolver or being returned from the ModeAndView.getView() method, the render method is going to be called to let the chosen View render itself. With the (optional) model from the ModelAndView class.

Exception Handling

When an exception occurs during processing of the request this exception is first being passed to the configured HandlerExceptionResolvers. If one of them can handle it the selected HandlerExceptionResolvers resolveException method is being invoked. This method, just like the HandlerAdapter.handle method can return a ModelAndView, when this happens this is processed in the same way as a normal request (see View Resolution).

Note: This is also to some degree documented in the javadoc of the DispatcherServlet. You can find all the default strategies and well known names in there, as well as a explanation of the request handling flow.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks so much for the wonderful explanation, I need to read it with full focus :). BTW, the way you have described the flow is awesome, I am curious to know how to build this kind of understanding (and so the confidence!). The books which I refer on Spring doesn't cover at the inner workings of the Spring and my mind always is thirsty on how this is working internally. The reference Documentation I feel slightly complicated (as of now), can you suggest me how to have better understanding, and not just "how to do a given task using the framework"? Thanks again!
Well that is 14 years of working with Spring, contributing to Spring and writing books about Spring. Also being a former Interface21/SpringSource consultant also helps :). But I like to know how things work, it is Open Source so look at the source code and read a couple of good books on the topic.
Impressive! BTW could you suggest some books both at beginner level and some at advanced level, including your book :).
2
  1. The controller does not read the xml file, Spring does.
  2. Your spring xml configuration is loaded in by Spring which wires everything together. Autowiring is taking place which is wiring by the Type, of which HandlerMapping1 can provide for the interface HandlerMapping.

    Interestingly BeanNameUrlHandlerMapping is the default handler mapping class, so it is the one created by the DispatcherServlet when Spring cannot find any handler mapping class declared.

    If you want to try and see something break, create a duplicate bean named HandlerMapping2 and read the error logging.

1 Comment

Thanks for your reply, so it means that Autowire by type is taking place. But in configuration file there is no mention of Autowire? Also, I tried duplicate bean as you suggested, however the application still works. I am more confused in this now!
1
  1. Spring framework reads the xml.
  2. Well, for spring MVC to work, the handler should be instantiated. The spring MVC framework needs to resolve the mappings and so we have handlers like BeanNameUrl..., ControllerBeanNameHandlerMapping, etc

    However, HandlerMapping is not generally used by your application code. So you need not specify whether this bean is autowired by type or not. It is used by the framework. So it is autowired in the framework classes by type.

    You can try defining the bean in the xml without any id, name something like

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    

    and it should still work.

    Id or name is required only when you want to refer to the bean by id or name for your use. Framework classes which need this handler mapping don't refer to the bean of HandlerMapping type by id or name. Framework will 'scan' the xml (or the loaded classes) and if it finds a concrete class in there of type (org.springframework.web.servlet.HandlerMapping) then it won't complain.

    To think of a similar case for example, when you run the junit tests, the engine will scan for all the methods annotated with @Test and it will 'know' that these are the methods it needs to execute as tests. It does not matter what the names of test methods are.

Hope this answers the query.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.