@ModelAttribute in Spring-MVC

@ModelAttribute refers to a property of the Model object (the M in MVC ;). @ModelAttribute is a Spring-MVC specific annotation used for preparing the model data. It is also used to define the command object that would be bound with the HTTP request data. The annotation works only if the class is a Controller class (i.e. annotated with @Controller).

ModelAttribute can be applied on both methods as well as method-parameters. It accepts an optional "value", which indicates the name of the attribute. If no value is supplied to the annotation, then the value would be defaulted to the return type name in case of methods and parameter type name in case of method-parameters.

The way Spring processes this annotation is,
  1. Before invoking the handler method, Spring invokes all the methods that have @ModelAttribute annotation. It adds the data returned by these methods to a temporary Map object. The data from this Map would be added to the final Model after the execution of the handler method.
  2. Then it prepares to invoke the the handler method. To invoke this method, it has to resolve the arguments. If the method has a parameter with @ModelAttribute, then it would search in the temporary Map object with the value of @ModelAttribute. If it finds, then the value from the Map is used for the handler method parameter.
  3. It it doesn't find it in the Map, then it checks if there is a SessionAttributes annotation applied on the controller with the given value. If the annotation is present, then the object is retrieved from the session and used for the handler method parameter. If the session doesn't contain the object despite of the @SessionAttributes, then an error is raised.
  4. If the object is not resolved through Map or @SessionAttribute, then it creates an instance of the parameter-type and passes it as the handler method parameter. Therefore, for it to create the instance, the parameter type should be a concrete-class-type (interfaces or abstract class types would again raise an error).
  5. Once the handler is executed, the parameters marked with @ModelAttributes are added to the Model.

Let me explain you further with the helps of some examples.

1.
@Controller
public class MyController {
 
    @ModelAttribute("myobject")
    public MyObject getInitializedMyObject() {
        return myService.getInitializedObject();
    }
 
    @RequestMapping(value="/handle.htm", method=RequestMethod.GET)
    public ModelAndView handleRequest() {
        return new ModelAndView("myView");
    }
 
}
In this example, the value returned by getInitializedMyObject is added to the Model. The View would be able to retrieve this object using the key "myobject" from the request attributes.

2.
@Controller
public class MyController {
 
    @ModelAttribute("myobject")
    public MyObject getInitializeMyObject() {
        return myService.getInitializedObject();
    }
 
    @RequestMapping(value="/handle.htm", method=RequestMethod.GET)
    public ModelAndView handleRequest(@ModelAttribute("myobject") MyObject myObject) {
        myObject.setValue("test");
        return new ModelAndView("myView");
    }
 
}
In this case, the getInitializeMyObject is executed first and the result is stored in a temporary map. This value is then passed as a parameter to the handler method. And finally myObject is added to the model for the views.

3.
@Controller
@SessionAttributes("myobject")
public class MyController {
 
    @RequestMapping(value="/handle.htm", method=RequestMethod.GET)
    public ModelAndView handleRequest(@ModelAttribute("myobject") MyObject myObject) {
        myObject.setValue("test");
        return new ModelAndView("myView");
    }
 
}

In this case, Spring searches for "myobject" in the session and pass it as the parameter to the handler method. If "myobject" is not found in the session, then HttpSessionRequiredException is raised.

4.
@Controller
public class MyController {
 
    @RequestMapping(value="/handle.htm", method=RequestMethod.GET)
    public ModelAndView handleRequest(@ModelAttribute("myobject") MyObject myObject) {
        myObject.setValue("test");
        return new ModelAndView("myView");
    }
 
}
In this case, a new instance of MyObject is created and then passed to handler method. If MyObject is an interface or an abstract class, then a BeanInstantiationException is raised.


19 comments:

  1. Hi Dinesh! I'm trying to use the @Pathvariable annotation to change my crud operations in my controller class. Can you help me? I'm using one of your tutorials
    http://www.dineshonjava.com/2012/12/spring-mvc-with-hibernate-crud-example.html#.U94xdXVdXQo.
    Thanks!

    ReplyDelete
  2. Any problem to using @PathVariable?

    ReplyDelete
  3. correction: private or protected(not privvate or public)
    For example: if the superclass method is declared public then the overridding method in the sub class cannot be either private or protected.

    ReplyDelete
  4. Hi Bassem,

    Thanks for this correction.
    And we also take some data from different different sites and program and practical we ran on my machine all codes are my own. I m sorry to forget to giving some references to some topics.

    ReplyDelete
  5. hello dinesh,
    tell me in a job process.when a process is executed a entry is gone into a database.suppose a process is executed at 7pm and end 8pm a entry is gone in database ..plz help me

    ReplyDelete
  6. Hi Vineet,

    Please look I have provide this type of example in Spring Batch Tutorial in next chapter.

    ReplyDelete
  7. Hi Dinesh Thank you for the Example. I would like to know whether we can integrate it with LDAP or any authentication server. For security verification.

    ReplyDelete
  8. Hi Dinesh,

    Yah its a nice tutorial,,But one doubt,after giving the correct name and password i couldnt able to get the welcome page.. am getting Error 404--Not Found...even i hav tat jsp in same location!!!! any idea!!!

    ReplyDelete
  9. Thank you very much for good example

    ReplyDelete
  10. Page Not Found when click for source code

    ReplyDelete
  11. It's not running :(

    ReplyDelete
  12. Thank you so much dinesh for presenting such a wonderful material

    ReplyDelete
  13. Really awesome explanation. I had searched a lot for this annotation, But this post has explained it quite well.

    ReplyDelete
  14. Thanks for learning with us...keep learning and like us on facebook as well for continuous notification about updates.

    ReplyDelete
  15. Hi Dinesh....
    Just tried ur json integration........ getting back the json, browser considers this as download and ask to save it, rather I want to display in the same way as in your example. Do I need to do something more for this
    thks

    ReplyDelete
  16. Nothing to do more in program please try this in the different browser!!!

    ReplyDelete