Spring MVC: How it works

Thursday, 23 November 2006

If you are interested in the Spring Framework’s MVC packages, this could be helpful. It’s a unified description of the life cycle of a web application or portlet request as handled by Spring Web MVC and Spring Portlet MVC. I created this for two reasons: I wanted a quick reference to the way Spring finds handlers for each stage of the request; and I wanted a unified view so I could see the similarities and differences between Web MVC and Portlet MVC.

Spring Web MVC, part of the Spring Framework, has long been a highly-regarded web application framework. With the recent release of Spring 2.0, Spring now supports portlet development with the Spring Portlet MVC package. Portlet MVC builds on Web MVC; even their documentation is similar. My focus right now is on portlet development, and I found it cumbersome to have to read the Web MVC and Portlet MVC documentation simultaneously. So I have re-edited the two together into one unified document. I have also included related information from elsewhere in the documentation, so it’s all in one place.

My idea here is to make it easy to go through your Spring configuration files and ensure that all beans are declared and named as they should be, whether you are using Spring Web MVC or Spring Portlet MVC.

Dispatcher

Spring’s Web and Portlet MVC are request-driven web MVC frameworks, designed around a servlet or portlet that dispatches requests to controllers. Spring’s dispatchers (DispatcherServlet and DispatcherPortlet) are also completely integrated with the Spring ApplicationContext and allow you to use every other feature Spring has.

The DispatcherServlet is a standard servlet (extending HttpServlet), and as such is declared in the web.xml of your web application. Requests that you want the DispatcherServlet to handle should be mapped using a URL mapping in the same web.xml file. Similarly, the DispatcherPortlet is a standard portlet (extending GenericPortlet), and as usual is declared in the portlet.xml of your web application. This is all standard J2EE configuration; here are a couple of examples.

From web.xml:

<web-app>
    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
	<!-- all requests ending with ".form" will be handled by Spring. -->
    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>
</web-app>

From portlet.xml:

<portlet>
	<portlet-name>sample</portlet-name>
	<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
	<supports>
		<mime-type>text/html</mime-type>
		<portlet-mode>view</portlet-mode>
	</supports>
	<portlet-info>
		<title>Sample Portlet</title>
	</portlet-info>
</portlet>

In the Portlet MVC framework, each DispatcherPortlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the portlet-specific scope, and new scope-specific beans can be defined local to a given portlet instance.

Dispatcher Workflow

When a DispatcherServlet or DispatcherPortlet is set up for use and a request comes in for that specific dispatcher, it starts processing the request. The sections below describe the complete process a request goes through when handled by such a dispatcher, from determining the application context right through to rendering the view.

Application context

For Web MVC only, the WebApplicationContext is searched for and bound in the request as an attribute in order for the controller and other elements in the process to use. It is bound by default under the key DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE.

Locale

The locale is bound to the request to let elements in the process resolve the locale to use when processing the request (rendering the view, preparing data, etc.). For Web MVC, this is the locale resolver. For Portlet MVC, this is the locale returned by PortletRequest.getLocale(). Note that locale resolution is not supported in Portlet MVC — this is in the purview of the portal/portlet container and is not appropriate at the Spring level. However, all mechanisms in Spring that depend on the locale (such as internationalisation of messages) will still function properly because DispatcherPortlet exposes the current locale in the same way as DispatcherServlet.

Theme

For Web MVC only, the theme resolver is bound to the request to let elements such as views determine which theme to use. The theme resolver does not affect anything if you don’t use it, so if you don’t need themes you can just ignore it. Theme resolution is not supported in Portlet MVC — this area is in the purview of the portal/portlet container and is not appropriate at the Spring level.

Multipart form submissions

For Web MVC and for Portlet MVC Action requests, if a multipart resolver is specified, the request is inspected for multiparts. If they are found, the request is wrapped in a MultipartHttpServletRequest or MultipartActionRequest for further processing by other elements in the process.

Handler mapping

Spring looks at all handler mappings (beans implementing the appropriate HandlerMapping interface) in the application context. Any that implement the Ordered interface are sorted (lowest order first), and others are added at the end of the list. The handler mappings are tried in order until one yields a handler. (Note: if the dispatcher’s detectAllHandlerMappings attribute is set to false, then this changes: Spring simply uses the handler mapping bean called “handlerMapping” and ignores any others.)

Handler

If a handler is found, the execution chain associated with the handler (pre-processors, controllers and post-processors) will be executed in order to prepare a model for rendering. The handler chain returns a View object or a view name, and normally also returns a model. For example, a pre-processor may block the request for security reasons and render its own view; in this case it will not return a model.

Note that the handler chain need not explicitly return a view or view name. If it does not, Spring creates a view name from the request path. For example, the path /servlet/apac/NewZealand.jsp yields the view name “apac/NewZealand”. This behaviour is implemented by an implicitly-defined DefaultRequestToViewNameTranslator bean; you can configure your own bean (which must be called “viewNameTranslator”) if you want to customise its behaviour.

Exceptions

Exceptions that are thrown during processing of the request go to the hander exception resolver chain. Spring looks at all hander exception resolvers (beans implementing the appropriate HandlerExceptionResolverinterface) in the application context. Any that implement the Ordered interface are sorted (lowest order first), and others are added at the end of the list. The resolvers are tried in order until one yields a model and view. (Note: if the dispatcher’s detectAllHandlerExceptionResolvers attribute is set to false, then this changes: Spring simply uses the hander exception resolver bean called “handlerExceptionResolver” and ignores any others.)

View resolver

If the handler chain returns a view name and a model, Spring uses the configured view resolvers to resolve the view name to a View. Spring looks at all view resolvers (beans implementing the ViewResolver interface) in the application context. Any that implement the Ordered interface are sorted (lowest order first), and others are added at the end of the list. Then the view resolvers are tried in order until one yields a view. (Note: if the dispatcher’s detectAllViewResolvers attribute is set to false, then this changes: Spring simply uses the view resolver bean called “viewResolver” and ignores any others.)

If the handler chain returns a View object, then no view resolution is necessary. Similarly, if it does not return a model, then no view will be rendered, so again no view resolution is necessary.

View

If we now have a view and a model, then Spring uses the view to render the model. This is what the user will see in the browser window or portlet.

Note: This information is excerpted and edited from The Spring Framework – Reference Documentation, which contains the following notice: “Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.”

Tags: , , ,

14 comments

You can leave a comment, or trackback from your own site.

  1. Hello Author,
    I am also exploring Spring Portlet MVC framework and your article give me a good start. Really a good job.
    I would love to learn this Framework and also if you can uplaod some sample
    HelloWorld portlet based on Spring Portlet MVC Framework, that would be great.

    Thanks again.
    Neeraj Sidhaye
    Try_Catch_Finally AT YAHOO DOT COM
    http://ExtremePortal.blog.co.uk

  2. Neeraj, the Spring Framework Reference Documentation has a lot of information in it. I recommend reading it in some depth. Also, the Spring CVS repository contains a sample portal application that showcases many portlet MVC features.

  3. Great post. I got a lot out of it.
    OK, I’m having a problem after posting a form, I can see the form posted and I can bind object. My issue is I have done a database lookup during the process and would like to display the results. How would I do that? all the methods that implement the “action” part of the Controller interface does not return a ModelAndView. Is it some basic Spring fundamental I’m missing?

  4. Steve, one approach is this: don’t do the DB lookup in your controller’s action handler. Instead, add a ParameterMappingInterceptor to your handler mapping so the form parameters will be included in the render request as well. Then do the DB lookup in the controller’s render handler and return the data in the ModelAndView.

    I’ve used this approach in my current project. It does mean that the DB query gets repeated with every render request though. If your DB query is especially heavyweight then you might need to do the query in the action handler and save the results in the portlet session.

  5. hi bennett,
    the article is great.
    but i suppose the flow could be more easily understood if u could do a code walkthrough(just a basic one) with the same amount of explanation.
    it would surely help anyone realise the concepts in a much better way.

  6. Saurav, that might indeed be helpful. It would take quite a while to write it up though. The controller hierarchy alone is fairly complex, with dozens of methods that can be overridden in the various classes. You really have to take the Reference Documentation’s advice and thouroughly review the javadocs for the entire hierarchy…

  7. Well can someone post an example for spring mvc using jdbcDaoSupport or simpleJdbc?. A web application where user can add, delete or update records in the database using spring mvc.

    Thanks

  8. Hi,

    That’s really a good post. Thanks for the work.

  9. Abhinav Shroff

    I am getting an exception in Spring MVC Portlet:

    javax.portlet.PortletException: No adapter for handler [com.hteinc.c2g.kr.spring.controllers.portlet.AccountsController@12db7c]: Does your handler implement a supported interface like Controller?

    This exception is thrown when the controller is supposed to be called as a default view from the interceptor.
    Please suggest a solution for it.

  10. This article was corrupted sometime recently; I’ve fixed it now, I hope.

  11. Very nice information for beginners ! I really appreciate this.

  12. Thanks for the detailed explanation.Really appreciate you work

  13. very good article

Leave a comment