Search This Blog

Tuesday 6 November 2012

The ModelAndView

In our previous example we did not explore the ModelAndView object in detail. We simply passed the control to a static jsp page. I modified the example to deal with a jsp with some dynamic content.
The modified XML configuration is as below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <value>
                /**/anything.do=defaultController
            </value>
        </property>
    </bean>

    <bean id="defaultController" class="com.mvc.controller.DataWelcomeController"></bean>

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

</beans>
As can be seen a different controller has been mapped to "anything.do" . The attributes of the view resolver have also been changed slightly. A prefix attribute has used here which means the .jsp files used for view generation are present at <webroot>/jsp/.
Consider the code for our controller:
public class DataWelcomeController implements Controller {

    @Override
    public ModelAndView handleRequest(final HttpServletRequest request,
            final HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = null;
        User user = new User();
        user.setAge(10);
        user.setName("Dummy user");

        User autoUser = new User();
        autoUser.setAge(11);
        autoUser.setName("Auto");

        String conTime = "CON TIME";
        //the view, attribute name and value
        modelAndView = new ModelAndView("data", "model", user);
        modelAndView.addObject(autoUser);//just the attribute - name auto-generated
        
        modelAndView.addObject("tpVariable", conTime);//atribute and name

        User testUser = new User();
        testUser.setAge(61);
        testUser.setName("Test user");

        Map<String, Object> modelMap = new LinkedHashMap<String, Object>();
        modelMap.put("testValue", "testValue");
        modelMap.put("int", 10);
        modelMap.put("tUser", testUser);

        modelAndView.addAllObjects(modelMap);// a map of attributes
        return modelAndView;
    }

}
As can be seen the ModelAndView exposes several methods to add attributes for use in the view. The constructor is also capable of accepting attribute as  name value pairs.(This is just like adding attributes to one of the scopes in a Servlet JSP application.)
In this case it has accepted the view name as the first parameter. The other two parameters are a name, value pair to be added in the scope.
There are also separate methods to add attributes. A special method allows us to just add an attribute, while its name is managed internally by the ModelAndView object. Internal methods like getVariableName(Object) of the org.springframework.core.Conventions class is used.
The jsp file for generating the view is
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Spring MVC Minimal</title>
    </head>
    <body>
        This is the model based view as JSP
        <br/>The first user is <%=request.getAttribute("model") %>
        <br/>The second user is <%=request.getAttribute("user") %>
        <br/>The third user is <%=request.getAttribute("tUser") %>
        <hr/>
        <p/>The string value is <%=request.getAttribute("testValue") %> 
         and  <%=request.getAttribute("tpVariable") %>
        while int value is  <%=request.getAttribute("int") %>
    </body>
</html>
On executing the code in a browser
The ModelAndView thus is simply a combination of the Model ( attributes that we added in the scope) and the view to be rendered by the Controller. Newer Applications prefer not to return ModelAndView instead simply returning the view as a string from their request handler methods.

7 comments:

  1. Thanks Robin for this wonderful post. I was searching for something like this..Thanks

    My email is nanosoft.indian@gmail.com.

    ReplyDelete
  2. I wanna say Thanks for clearing all my doubts!

    ReplyDelete
  3. Can you please tell me, How will the expression "<%=request.getAttribute("user") %>" identifies the object "autoUser " of User with out mentioning the attribute name?
    If Spring manages internally what is the name that it internally gives? How can we code just "request.getAttribute("user")" and gets the autoUser details.. Please do clarify..

    ReplyDelete
    Replies
    1. I believe Spring saves the object with the name of the class, So the object autoUser of type User was saved with attribute name "user"
      Sorry, I am talking from memory, so if you see a different behavior do let me know. For instance, check if you can add two objects of the same class. How would you retrieve them ? Does Spring just return the last added instance ? Or it throws an error ? Food for thought...

      Delete
  4. How "The first user is '<%=request.getAttribute("model") %>" is able to print
    "The first user is Dummy User and age is 10"?
    My query is that from where it got this string "Dummy User and age is 10"??

    Also can you please share code of User class as well, i am hoping this comes from the constructor of user class.

    ReplyDelete
    Replies
    1. I would assume that User is a simple POJO and has a toString() method that returns name + " and age is " + age.

      Delete