Spring @ModelAttribute Annotation

Spring @ModelAttribute annotation is used to bind a method parameter or method return value to a named model attribute which further can be used in the view page.

It can be used either at the method level or method parameter level.

@ModelAttribute at a Method Level

We can use this annotation at the method level to specify that this method may add one or model attributes.

@PostMapping("save")
@ModelAttribute("user") 
public String save(User user, Model model) {	
	model.addAttribute("user", user);
	return "response";
}

@ModelAttribute at a Method Argument

We can use it with the method argument that indicates the argument should be retrieved from the model. If the argument is not present then first it should be instantiated and then added to the model.

See in this example, we used @ModelAttribute with the argument.

@PostMapping("save")
public String save(@ModelAttribute("user") User user, Model model) {	
	model.addAttribute("user", user);
	return "response";
}

Time for an Example

Let's understand by example. Here, we are creating a Spring MVC application and in its controller class we used @ModelAttribute annotation.

The following are the source files of our project the AppConfig and MainApp both are configuration files for Spring MVC.

// AppConfig.java

This is our application configuration file that implements WebMvcConfugurer interface to make this MVC application and created a method viewResolver to map our views files(JSP).

package com.studytonight;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("com.studytonight")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

// MainApp.java

This class initializes our web application and creates ServletContext by using that we register our AppConfig class(above file).

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	

	}
}

// UserController.java

This is our controller class in which we used @ModelAttribute and method parameters to fetch the model data into view file.

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.studytonight.model.User;

@Controller
public class UserController {
	
	@GetMapping("/")
	public String index(Model model) {
		model.addAttribute("user", new User());
		return "index";
	}
	
	@PostMapping("save")
	public String save(@ModelAttribute("user") User user, Model model) {	
		model.addAttribute("user", user);
		return "response";
	}
}

// User.java

package com.studytonight.model;

public class User {

	private int id;
	private String name;
	private String email;
	private String password;
	private String confirm_password;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getConfirm_password() {
		return confirm_password;
	}
	public void setConfirm_password(String confirm_password) {
		this.confirm_password = confirm_password;
	}
}

// index.jsp

In this JSP page, we used modelAttribute to map with the @ModelAttribute parameter to bind the form data with the model.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
	<form:form action="save" method="post" modelAttribute="user">
		User Name: <form:input type="text" path="name" />
		<br>
		<br>
		Email: <form:input type="email" path="email" style="margin-left:34px;" />
		<br>
		<br> 
		Password: <form:input type="password" path="password"  style="margin-left:10px;" />
		<br>
		<br>
		Confirm Password: <form:input type="password" path="confirm_password" />
		<br>
		<br>
		<input type="submit" value="Register">
	</form:form>
</body>
</html>

// response.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Response User Data</title>
</head>
<body>
	<h2>${user.name}</h2>
	<p>Email: ${user.email}</p>
	<p>Password: ${user.password}</p>
</body>
</html>

// pom.xml

This file contains all the dependencies of this project such as spring jars, servlet jars, etc. Put these dependencies into your project to run the application.

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
			</plugin>
		</plugins>
	</build>
</project>

Run the Application

After successfully completing the project and adding the dependencies run the application using the server and you will get the output as below.

Enter User Information

Retrieve Data