In SpringMVC, @ModelAttribute is used at 2 places.1. At Method level2. At Method parameter level.How @ModelAttribute at method level works?
package com.customer.controller;import java.sql.Date;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import org.springframework.beans.propertyeditors.CustomDateEditor;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.validation.BindingResult;import org.springframework.web.bind.WebDataBinder;import org.springframework.web.bind.annotation.InitBinder;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.support.SessionStatus;import com.customer.model.Customer;@Controller@RequestMapping("/customer.htm")public class CustomerController{ @RequestMapping(method = RequestMethod.POST) public String processSubmit(@ModelAttribute("customer") Customer customer, BindingResult result, SessionStatus status) { System.out.println("Parameter Level ModelAttriute is executed"); if (result.hasErrors()) { return "CustomerForm"; } else { status.setComplete(); return "CustomerSuccess"; } } @RequestMapping(method = RequestMethod.GET) public String initForm(ModelMap model){ System.out.println("initForm method is executed (GET)"); Customer cust = new Customer(); cust.setFavFramework(new String []{"Spring MVC"}); cust.setSex("M"); cust.setJavaSkills("Hibernate"); cust.setSecretValue("I'm hidden value"); model.addAttribute("customer", cust); return "CustomerForm"; } @ModelAttribute("webFrameworkList") public ListpopulateWebFrameworkList() { System.out.println("Method Level ModelAttriute is executed (populateWebFrameworkList)"); List webFrameworkList = new ArrayList (); webFrameworkList.add("Spring MVC"); webFrameworkList.add("Struts 1"); webFrameworkList.add("Struts 2"); webFrameworkList.add("JSF"); webFrameworkList.add("Apache Wicket"); return webFrameworkList; } @InitBinder public void initBinder(WebDataBinder binder) { System.out.println("initBinder method is executed"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); } @ModelAttribute("numberList") public List populateNumberList() { System.out.println("Method Level ModelAttriute is executed (populateNumberList)"); List numberList = new ArrayList (); numberList.add("Number 1"); numberList.add("Number 2"); numberList.add("Number 3"); numberList.add("Number 4"); numberList.add("Number 5"); return numberList; } @ModelAttribute("javaSkillsList") public Map populateJavaSkillList() { System.out.println("Method Level ModelAttriute is executed (populateJavaSkillList)"); Map javaSkill = new LinkedHashMap (); javaSkill.put("Hibernate", "Hibernate"); javaSkill.put("Spring", "Spring"); javaSkill.put("Apache Wicket", "Apache Wicket"); javaSkill.put("Struts", "Struts"); return javaSkill; } @ModelAttribute("countryList") public Map populateCountryList() { System.out.println("Method Level ModelAttriute is executed (populateCountryList)"); Map country = new LinkedHashMap (); country.put("US", "United Stated"); country.put("CHINA", "China"); country.put("SG", "Singapore"); country.put("MY", "Malaysia"); return country; } }
|
Explanation:if I access this URL: http://localhost:5060/SpringMVC/customer.htm then if we find the logging details in the console, then we can get the clear cut picture of @ModelAttribute flowConsole Output This Shows that it follows 3 rulesRule-1: If the @ModelAttribute is used at Method level, then those methods are executed first, remaining methods (which are not annotated with @ModelAttribute) are executed with the help of @RequestMapping annotation. Rule-2: If more than one method in the controller are annotated with the @ModelAttribute, then the execution follows the sequence order of the @ModelAttribute annotated methods.(Check the output)Rule-3: If the method parameter is annotated with @ModelAttribute, those methods are executed w.r.t @RequestMapping annotation. Ex: During the submit button execution (in controller it is POST)Work FlowDuring the execution of the handler method, you see CommandObject has been added to the Spring model attributes, but it is not yet in the HttpServletRequest or HttpSession scope. But after the handler method has executed and when the nextpage.jsp is rendered, you can see that the model attribute data (CommandObject) has indeed been copied as an attribute (with the same attribute key) to both HttpServletRequest and HttpSession. Note-1: No need to write any code to set the model attribute into the request scope.Note-2: we need to use @SessionAttributes at the class level in the controller class to set the model attributes into the session scope. How @ModelAttribute at method parameter level works?Case-1: jsp to controllerCase-2: Controller to jsp