@ModelAttribute
Binding form fields and query parameters to objects — WebDataBinder, nested and collection binding, validation with BindingResult, global model data and @ModelAttribute vs @RequestBody.
#Introduction
@ModelAttribute is one of the most misunderstood annotations in Spring. Many developers think it's only for HTML forms. In reality it's used for Spring MVC form binding, request-parameter binding, global model data, view rendering, data preloading, edit forms and legacy enterprise applications.
Interviewers frequently ask: What is @ModelAttribute? How is it different from @RequestBody? When should we use it? How does Spring populate the object? Can it work without the annotation? Which internal class handles it?
#What is @ModelAttribute?
Unlike @RequestBody, it does not read JSON. Instead it binds:
- Query parameters
- Form data (
application/x-www-form-urlencoded) - Multipart form fields (non-file fields)
First Example
POST /users
Content-Type: application/x-www-form-urlencoded
name=Rahul&age=25@PostMapping("/users")
public String save(@ModelAttribute UserForm form) {
return "Saved";
}Spring automatically does the equivalent of:
UserForm form = new UserForm();
form.setName("Rahul");
form.setAge(25);No JSON parsing happens.
Complete Request Flow
#Why Do We Need @ModelAttribute?
Without Spring:
UserForm form = new UserForm();
form.setName(request.getParameter("name"));
form.setAge(Integer.parseInt(request.getParameter("age")));With Spring, @ModelAttribute UserForm form — everything is automatic.
#Data Sources
@ModelAttribute binds values from query parameters, form fields and multipart form fields — e.g. GET /users?name=Rahul&age=25 or a POST with Content-Type: application/x-www-form-urlencoded.
GET Example
@GetMapping("/search")
public String search(@ModelAttribute SearchFilter filter) {
}GET /search?city=Bangalore&active=true → SearchFilter { city = Bangalore, active = true }.
POST Form Example
<form action="/users" method="post">
<input name="name">
<input name="age">
<button>Save</button>
</form>@PostMapping("/users")
public String save(@ModelAttribute UserForm form) {
}Spring fills the object automatically.
#Nested Object Binding
name=Rahul
address.city=Bangalore
address.state=Karnatakapublic class UserForm {
private Address address;
}
public class Address {
private String city;
private String state;
}Spring binds address.city → Address.city automatically.
#Collection Binding
skills[0]=Java
skills[1]=Spring
skills[2]=MySQLprivate List<String> skills;Spring populates the list.
#Validation and BindingResult
public class UserForm {
@NotBlank
private String name;
@Min(18)
private Integer age;
}
@PostMapping
public String save(@Valid @ModelAttribute UserForm form) {
}Validation executes after binding.
BindingResult
A favourite interview question.
@PostMapping
public String save(@Valid @ModelAttribute UserForm form,
BindingResult result) {
if (result.hasErrors()) {
return "user-form";
}
return "success";
}Instead of throwing an exception, validation errors stay inside BindingResult. This is especially useful for server-rendered forms (redisplay the form with error messages).
#@ModelAttribute on Methods — Global Model Data
@ModelAttribute can also be placed on methods:
@Controller
public class UserController {
@ModelAttribute("countries")
public List<String> countries() {
return List.of("India", "USA", "Japan");
}
}Every view rendered by this controller receives countries automatically. (These methods run before each handler method in the controller.)
Across All Controllers
@ControllerAdvice
public class GlobalModel {
@ModelAttribute("applicationName")
public String app() {
return "Ticket Booking";
}
}Now every view receives applicationName. Common in Spring MVC applications.
#@ModelAttribute vs @RequestBody
One of the most common interview questions.
| @ModelAttribute | @RequestBody |
|---|---|
| Form data, query parameters | JSON / XML request body |
Uses WebDataBinder | Uses HttpMessageConverter |
| HTML forms | REST APIs |
| No JSON parsing | JSON parsing |
#@ModelAttribute vs @RequestParam
For GET /users?name=Rahul&age=25:
// Option 1
@RequestParam String name, @RequestParam Integer age
// Option 2 — better when there are many fields
@ModelAttribute UserFilter filter#File Upload Example
name=Rahul
age=25
profilePhoto=file.jpg@PostMapping("/upload")
public String upload(@ModelAttribute UserForm form,
@RequestParam MultipartFile profilePhoto) {
}@ModelAttribute binds the form fields; MultipartFile handles the uploaded file.
#Internal Working
Important classes: ModelAttributeMethodProcessor, WebDataBinder, ConversionService and Validator — interview favourites.
#@ModelAttribute Without the Annotation
For complex (non-simple) types in Spring MVC controllers, Spring treats the parameter as a model attribute even if you omit the annotation:
@PostMapping
public String save(UserForm form) {
}Spring binds request parameters into form automatically. Adding @ModelAttribute makes the intent explicit and is recommended for readability.
#Common Mistakes
- Using
@RequestBodyfor HTML forms. HTML forms usually submitapplication/x-www-form-urlencoded, so@RequestBody UserFormfails (415). Use@ModelAttribute UserForm form. - Using
@ModelAttributefor JSON. APOSTwithContent-Type: application/jsonneeds@RequestBody UserDto dto; with@ModelAttributethe fields staynull. - Forgetting
BindingResultfor server-rendered forms — it lets you redisplay validation errors instead of throwing. - Mixing REST and MVC concepts. REST APIs →
@RequestBody+ JSON. HTML forms →@ModelAttribute+ form data.
#Enterprise Architecture
#Interview Questions
Q1What is @ModelAttribute?
It binds request parameters or form fields to a Java object and adds that object to the model for view rendering.
Q2What is the difference between @ModelAttribute and @RequestBody?
@ModelAttributebinds query parameters and form data.@RequestBodybinds the HTTP request body (typically JSON or XML).
Q3Which Spring class processes @ModelAttribute?
ModelAttributeMethodProcessor.
Q4What is WebDataBinder?
The component that binds request parameters to Java object properties and coordinates type conversion and validation.
Q5What is BindingResult?
It stores binding and validation errors after @ModelAttribute processing, so the application can redisplay the form with error messages instead of throwing an exception.
Q6Can @ModelAttribute bind nested objects?
Yes — e.g. address.city → User.address.city.
Q7Can @ModelAttribute bind collections?
Yes — lists, arrays, maps and nested collections, using indexed property names.
Q8Can @ModelAttribute be used on methods?
Yes. Methods annotated with @ModelAttribute add common data to the model before controller methods execute.
Q9When should we use @ModelAttribute?
HTML form submissions, search/filter forms, Spring MVC applications, view rendering with model data, and multipart form requests (for the non-file fields).
#Summary
#Key Takeaways
@ModelAttributebinds request parameters and form fields to Java objects.- It's designed for Spring MVC and HTML form processing, not JSON REST APIs.
ModelAttributeMethodProcessorcreates and binds the object.WebDataBinderhandles property binding, type conversion and validation.BindingResultcaptures validation errors for server-rendered forms.@ModelAttributemethods provide common model data, per controller or globally via@ControllerAdvice.- Prefer
@RequestBodyfor REST APIs and@ModelAttributefor form submissions.