In this post, we discuss @ModelAttribute annotation available in Spring MVC.
Introduction
The @ModelAttribute annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view. Supported for controller classes with @RequestMapping
methods. Spring MVC will invoke all methods with @ModelAttribute
annotation before any handler method executed by the framework. An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model.
1. The @ModelAttribute
Annotation
The @ModelAttribute annotation can be used at method and method parameter level. Let’s take a look at both use cases for better understanding.
1.1 Method Level Annotation
Method level @ModelAttribute
annotation is useful when we always like to populated model with certain attributes. Method level ModelAttribute annotation cannot be mapped directly with any request. Let’s take a look at the following example for better understanding.
@Controller
public class DemoController {
/**
* This method demonstrate the use @ModelAttribute annotation at the method level.
* This method create a list and returns list of countries
*
* @return list of countries
*/
@ModelAttribute("countries")
public List < String > getCountries() {
List < String > countries = new ArrayList < > ();
countries.add("UK");
countries.add("USA");
countries.add("Japan");
return countries;
}
/**
*This method is the variation of the above method.It will accept a model and save values in this mode.
* These saved values will be available on the frontend to the custom
*
* @param model
*/
@ModelAttribute
public void (final Model model) {
List < String > states = new ArrayList < > ();
states.add("California");
states.add("New York");
states.add("Alaska");
states.add("Colorado");
model.addAttribute("states", states);
}
}
We have 2 different methods in the above example.
- The first example creates and returns a list of countries.
- The second example takes Model as an argument, create a list of states and save that list in the model.
Spring MVC makes a call to getCountries()
and getStates()
methods (annotated with @ModelAttribute
)before the controller methods annotated with @RequestMapping
are invoked. This sequence ensures that the model object is available before request processing starts in the Spring controller.
1.2 Method Argument
In case we use @ModelAttribute annotation at the method level, it tells Spring MVC that the method argument should be retrieved from the model. Let’s keep in mind the following important points.
- The framework tries to find this argument from the model, in case this is not available, it first creates and adds it to the model.
Let’s extend our previous example to add a method with @ModelAttribute annotation. We added another method in the above code, here is the code snippet.
/*
* A handler method can have more then one parameters with @ModelAttribute
* The following handler method will retrieve the 'countries','cities' and 'languages'
* attribute from the model
*/
@GetMapping("/home")
public String home(@ModelAttribute("countries") List < String > countries,Model model) {
//Add more countries
countries.add("Australia");
countries.add("Canada");
return "home";
}
Above is going to bind form data with the Java object. As opposed to the method level annotation, a method with request handling annotation (@GetMapping
in our case), can have a parameter with @ModelAttribute
annotation.
2. Frontend View
Let’s create a very basic example to help you understand the above workflow. We are creating a simple HTML form using Thymeleaf. Let’s take a look at the example first before we get into more details.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Demo Application to demonstrae @ModelAttribute annotation</title>
</head>
<body>
<h4>Country List</h4>
<tr th:each="country: ${countries}">
<td th:text="${country}" />
<td><br/></td>
</tr>
<h4>States</h4>
<tr th:each="state: ${states}">
<td th:text="${state}" />
<td><br/></td>
</tr>
</body>
</html>
This is a very simple example which print list of the countries and states based on the data available to the Spring MVC controller. Let’s take a look the HTML view.
In the above example, we added some additional countries in the home()
method while SPring MVC called getStates()
method to fetch a list of states saved in the model.
Summary
In this post, we got an overview of the @ModelAttribute annotation. We quickly covered the different options to use the model attribute annotation in your Spring application. Check out the Github repository for the source code.