Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ModelAttribute annotation, when to use it?

Lets say we have an entity Person, a controller PersonController and an edit.jsp page (creating a new or editing an existing person)

Controller

@RequestMapping(value = "/edit", method = RequestMethod.POST) public String editPerson(@RequestParam("fname") String fname, Model model) {     if(fname == null || fname.length() == 0){         model.addAttribute("personToEditOrCreate", new Person());     }     else{         Person p = personService.getPersonByFirstName(fname);         model.addAttribute("personToEditOrCreate", p);     }      return "persons/edit"; }  @RequestMapping(value = "/save", method = RequestMethod.POST) public String savePerson(Person person, BindingResult result) {      personService.savePerson(person);     return "redirect:/home"; } 

edit.jsp

<form:form method="post" modelAttribute="personToEditOrCreate" action="save">     <form:hidden path="id"/>      <table>         <tr>             <td><form:label path="firstName">First Name</form:label></td>             <td><form:input path="firstName" /></td>         </tr>         <tr>             <td><form:label path="lastName">Last Name</form:label></td>             <td><form:input path="lastName" /></td>         </tr>         <tr>             <td><form:label path="money">Money</form:label></td>             <td><form:input path="money" /></td>         </tr>         <tr>             <td colspan="2">                 <input type="submit" value="Add/Edit Person"/>             </td>         </tr>     </table>   </form:form> 

Im trying the code above (without using the @ModelAttribute annotation in the savePerson method, and it works correct. Why and when do i need to add the annotation to the person object:

@RequestMapping(value = "/save", method = RequestMethod.POST) public String savePerson(@ModelAttribute("personToEditOrCreate") Person person, BindingResult result) {      personService.savePerson(person);     return "redirect:/home"; } 
like image 219
user711189 Avatar asked Dec 31 '11 12:12

user711189


People also ask

Can we use @ModelAttribute as a method argument?

As described in the Spring MVC documentation - the @ModelAttribute annotation can be used on methods or on method arguments.

What is the difference between @ModelAttribute and @RequestBody?

@ModelAttribute is used for binding data from request param (in key value pairs), but @RequestBody is used for binding data from whole body of the request like POST,PUT.. request types which contains other format like json, xml.

Which one of the given options @ModelAttribute annotation can be declared?

The @ModelAttribute annotation can be used at the parameter level or the method level. The use of this annotation at the parameter level is to accept the request form values while at the method level is to assign the default values to a model.

Why do we use @ModelAttribute?

The @ModelAttribute annotation is used as part of a Spring MVC web app and can be used in two scenarios. Firstly, it can be used to inject data objects in the model before a JSP loads. This makes it particularly useful by ensuring that a JSP has all the data it needs to display itself.


Video Answer


2 Answers

You don't need @ModelAttribute (parameter) just to use a Bean as a parameter

For example, these handler methods work fine with these requests:

@RequestMapping("/a") void pathA(SomeBean someBean) {   assertEquals("neil", someBean.getName()); }  GET /a?name=neil  @RequestMapping(value="/a", method=RequestMethod.POST) void pathAPost(SomeBean someBean) {   assertEquals("neil", someBean.getName()); }  POST /a name=neil 

Use @ModelAttribute (method) to load default data into your model on every request - for example from a database, especially when using @SessionAttributes. This can be done in a Controller or in a ControllerAdvice:

@Controller @RequestMapping("/foos") public class FooController {    @ModelAttribute("foo")   String getFoo() {     return "bar";  // set modelMap["foo"] = "bar" on every request   }  } 

Any JSP forwarded to by FooController:

${foo} //=bar 

or

@ControllerAdvice public class MyGlobalData {    @ModelAttribute("foo")   String getFoo() {     return "bar";  // set modelMap["foo"] = "bar" on every request   }  } 

Any JSP:

${foo} //=bar 

Use @ModelAttribute (parameter) if you want to use the result of @ModelAttribute (method) as a default:

@ModelAttribute("attrib1") SomeBean getSomeBean() {   return new SomeBean("neil");  // set modelMap["attrib1"] = SomeBean("neil") on every request }  @RequestMapping("/a") void pathA(@ModelAttribute("attrib1") SomeBean someBean) {   assertEquals("neil", someBean.getName()); }  GET /a 

Use @ModelAttribute (parameter) to get an object stored in a flash attribute:

@RequestMapping("/a") String pathA(RedirectAttributes redirectAttributes) {   redirectAttributes.addFlashAttribute("attrib1", new SomeBean("from flash"));   return "redirect:/b"; }  @RequestMapping("/b") void pathB(@ModelAttribute("attrib1") SomeBean someBean) {   assertEquals("from flash", someBean.getName()); }  GET /a 

Use @ModelAttribute (parameter) to get an object stored by @SessionAttributes

@Controller @SessionAttributes("attrib1") public class Controller1 {      @RequestMapping("/a")     void pathA(Model model) {         model.addAttribute("attrib1", new SomeBean("neil")); //this ends up in session due to @SessionAttributes on controller     }      @RequestMapping("/b")     void pathB(@ModelAttribute("attrib1") SomeBean someBean) {         assertEquals("neil", someBean.getName());     } }  GET /a GET /b 

like image 79
Neil McGuigan Avatar answered Sep 28 '22 07:09

Neil McGuigan


Your question appears to be answered already:

What is @ModelAttribute in Spring MVC?

To summarize the answer and blog post: when you want your form backing object (instance of Person) to be persisted across requests.

Otherwise, without the annotation, the request mapped method will assume Person is a new object and in no way linked to your form backing object. The blog post that poster references is really awesome by the way, definitely a must-read.

like image 36
abelito Avatar answered Sep 28 '22 09:09

abelito