What is #ModelAttribute in Spring MVC? - java

What is the purpose and usage of #ModelAttribute in Spring MVC?

#ModelAttribute refers to a property of the Model object (the M in MVC ;)
so let's say we have a form with a form backing object that is called "Person"
Then you can have Spring MVC supply this object to a Controller method by using the #ModelAttribute annotation:
public String processForm(#ModelAttribute("person") Person person){
person.getStuff();
}
On the other hand the annotation is used to define objects which should be part of a Model.
So if you want to have a Person object referenced in the Model you can use the following method:
#ModelAttribute("person")
public Person getPerson(){
return new Person();
}
This annotated method will allow access to the Person object in your View, since it gets automatically added to the Models by Spring.
See "Using #ModelAttribute".

I know this is an old thread, but I thought I throw my hat in the ring and see if I can muddy the water a little bit more :)
I found my initial struggle to understand #ModelAttribute was a result of Spring's decision to combine several annotations into one. It became clearer once I split it into several smaller annotations:
For parameter annotations, think of #ModelAttribute as the equivalent of #Autowired + #Qualifier i.e. it tries to retrieve a bean with the given name from the Spring managed model. If the named bean is not found, instead of throwing an error or returning null, it implicitly takes on the role of #Bean i.e. Create a new instance using the default constructor and add the bean to the model.
For method annotations, think of #ModelAttribute as the equivalent of #Bean + #Before, i.e. it puts the bean constructed by user's code in the model and it's always called before a request handling method.
Figuratively, I see #ModelAttribute as the following (please don't take it literally!!):
#Bean("person")
#Before
public Person createPerson(){
return new Person();
}
#RequestMapping(...)
public xxx handlePersonRequest( (#Autowired #Qualifier("person") | #Bean("person")) Person person, xxx){
...
}
As you can see, Spring made the right decision to make #ModelAttribute an all-encompassing annotation; no one wants to see an annotation smorgasbord.

So I will try to explain it in simpler way. Let's have:
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
As described in the Spring MVC documentation - the #ModelAttribute annotation can be used on methods or on method arguments. And of course we can have both use at the same time in one controller.
1.Method annotation
#ModelAttribute("cities")
public List<String> checkOptions(){
return new Arrays.asList(new[]{"Sofia","Pleven","Ruse"});//and so on
}
Purpose of such method is to add attribute in the model. So in our case cities key will have the list new Arrays.asList(new[]{"Sofia","Pleven","Ruse"}) as value in the Model (you can think of Model as map(key:value)). #ModelAttribute methods in a controller are invoked before #RequestMapping methods, within the same controller.
Here we want to add to the Model common information which will be used in the form to display to the user. For example it can be used to fill a HTML select:
2.Method argument
public String findPerson(#ModelAttriute(value="person") Person person) {
//..Some logic with person
return "person.jsp";
}
An #ModelAttribute on a method argument indicates the argument should be retrieved from the model. So in this case we expect that we have in the Model person object as key and we want to get its value and put it to the method argument Person person. If such does not exists or (sometimes you misspell the (value="persson")) then Spring will not find it in the Model and will create empty Person object using its defaults. Then will take the request parameters and try to data bind them in the Person object using their names.
name="Dmitrij"&countries=Lesoto&sponsor.organization="SilkRoad"&authorizedFunds=&authorizedHours=&
So we have name and it will be bind to Person.name using setName(String name). So in
//..Some logic with person
we have access to this filled name with value "Dimitrij".
Of course Spring can bind more complex objects like Lists, Maps, List of Sets of Maps and so on but behind the scene it makes the data binding magic.
We can have at the same time model annotated method and request method handler with #ModelAttribute in the arguments. Then we have to union the rules.
Of course we have tons of different situations - #ModelAttribute methods can also be defined in an #ControllerAdvice and so on...

For my style, I always use #ModelAttribute to catch object from spring form jsp. for example, I design form on jsp page, that form exist with commandName
<form:form commandName="Book" action="" methon="post">
<form:input type="text" path="title"></form:input>
</form:form>
and I catch the object on controller with follow code
public String controllerPost(#ModelAttribute("Book") Book book)
and every field name of book must be match with path in sub-element of form

I know I am late to the party, but I'll quote like they say,
"better be late than never". So let us get going,
Everybody has their own ways to explain things, let me try to sum it up and simple it up for you in a few steps with an example;
Suppose you have a simple form, form.jsp:
<form:form action="processForm" modelAttribute="student">
First Name : <form:input path="firstName" />
<br/><br/>
Last Name : <form:input path="lastName" />
<br/><br/>
<input type="submit" value="submit"/>
</form:form>
<form:input path="firstName" /> <form:input path="lastName" /> These are the fields/properties in the Student class. When the form is called/initialized their getters are invoked. On form submit their setters are invoked, and their values are transferred in the bean that was indicated with modelAttribute="student" in the form tag.
We have StudentController that includes the following methods:
#RequestMapping("/showForm")
// `Model` is used to pass data between controllers and views
public String showForm(Model theModel) {
// attribute name, value
theModel.addAttribute("student", new Student());
return "form";
}
#RequestMapping("/processForm")
public String processForm(#ModelAttribute("student") Student theStudent) {
System.out.println("theStudent :"+ theStudent.getLastName());
return "form-details";
}
//#ModelAttribute("student") Student theStudent
//Spring automatically populates the object data with form data
//all behind the scenes
Now finally we have a form-details.jsp:
<b>Student Information</b>
${student.firstName}
${student.lastName}
So back to the question What is #ModelAttribute in Spring MVC?
A sample definition from the source for you,
http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation
The #ModelAttribute is an annotation that binds a method parameter or method return value to a named model attribute and then exposes it to a web view.
What actually happens is it gets all the values of your form those were submitted by it and then holds them for you to bind or assign them to the object. It works like the #RequestParameter where we only get a parameter and assign the value to some method argument.
The difference is that #ModelAttribute holds all form data rather than a single parameter. It creates a bean for you which holds the data submitted in the form.
To recap the whole thing:
Step 1:
A request is sent and our method showForm() runs and a model, a temporary bean, is set with the name student and forwarded to the form:
theModel.addAttribute("student", new Student());
Step 2:
Form attribute modelAttribute="student" defines that on form submission the model will update the student and will hold all parameters of the form.
Step 3:
On form submission the processForm() method is invoked with parameter #ModelAttribute("student") Student theStudent: the values being hold in the form with modelAttribute="student" were fetched and assigned to the fields in the Student object.
Step 4:
And then we use it as we bid, just like showing it on the page etc like I did
I hope it helps you to understand the concept. Thanks

Take any web application whether it is Gmail or Facebook or Instagram or any other web application, it's all about exchanging data or information between the end user and the application or the UI and the back end application. Even in Spring MVC world there are two ways to exchange data:
from the Controller to the UI, and
from the UI to the Controller.
What we are interested here is how the data is communicated from the UI to Controller. This can also be done in 2 ways:
Using an HTML Form
Using Query Parameters.
Using an HTML Form:
Consider the below scenario,
When we submit the form data from the web browser, we can access that data in our Controller class as an object. When we submit an HTML form, the Spring Container does four things. It will,
first read all the data that is submitted that comes in the request using the request.getParameter method.
once it reads them, it will convert them into the appropriate Java type using integer.parseInt, double.parseDouble and all the other parse methods that are available based on the data type of the data.
once parsed, it will create a object of the model class that we created. For example, in this scenario, it is the user information that is being submitted and we create a class called User, which the Container will create an object of and it will set all the values that come in automatically into that object.
it will then handover that object by setting the values to the Controller.
To get this whole thing to work, we'll have to follow certain steps.
We first need to define a model class, like User, in which the number of fields should exactly match the number of fields in the HTML form. Also, the names that we use in the HTML form should match the names that we have in the Java class. These two are very important. Names should match, the number of fields in the form should match the number of fields in the class that we create. Once we do that, the Container will automatically read the data that comes in, creates an object of this model, sets the values and it hands it over to the Controller. To read those values inside the Controller, we use the #ModelAttribute annotation on the method parameters. When we create methods in the Controller, we are going to use the #ModelAttribute and add a parameter to it which will automatically have this object given by the Container.
Here is an example code for registering an user:
#RequestMapping(value = "registerUser", method = RequestMethod.POST)
public String registerUser(#ModelAttribute("user") User user, ModelMap model) {
model.addAttribute("user", user);
return "regResult";
}
Hope this diagrammatic explanation helped!

#ModelAttribute can be used as the method arguments / parameter or before the method declaration.
The primary objective of this annotation to bind the request parameters or form fields to an model object
Ref. http://www.javabeat.net/modelattribute-spring-mvc/

This is used for data binding purposes in Spring MVC. Let you have a jsp having a form element in it e.g
on JSP
<form:form action="test-example" method="POST" commandName="testModelAttribute"> </form:form>
(Spring Form method, Simple form element can also be used)
On Controller Side
#RequestMapping(value = "/test-example", method = RequestMethod.POST)
public ModelAndView testExample(#ModelAttribute("testModelAttribute") TestModel testModel, Map<String, Object> map,...) {
}
Now when you will submit the form the form fields values will be available to you.

Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view.
public String add(#ModelAttribute("specified") Model model) {
...
}

#ModelAttribute will create a attribute with the name specified by you (#ModelAttribute("Testing") Test test) as Testing in the given example ,Test being the bean test being the reference to the bean and Testing will be available in model so that you can further use it on jsp pages for retrieval of values that you stored in you ModelAttribute.

#ModelAttribute simply binds the value from jsp fields to Pojo calss to perform our logic in controller class. If you are familiar with struts, then this is like populating the formbean object upon submission.

The ModelAttribute annotation is used as part of a Spring MVC Web application and can be used in two scenarios.
First of all, it can be used to inject data into a pre-JSP load model. This is especially useful in ensuring that a JSP is required to display all the data itself. An injection is obtained by connecting one method to the model.
Second, it can be used to read data from an existing model and assign it to the parameters of the coach's method.
refrence https://dzone.com/articles/using-spring-mvc%E2%80%99s

At the Method Level
1.When the annotation is used at the method level it indicates the purpose of that
method is to add one or more model attributes
#ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("india", "india");
}
At the Method Argument
1. When used as a method argument, it indicates the argument should be retrieved from the model. When not present and should be first instantiated and then added to the model and once present in the model, the arguments fields should be populated from all request parameters that have matching names So, it binds the form data with a bean.
#RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(#ModelAttribute("employee") Employee employee) {
return "employeeView";
}

First of all, Models are used in MVC Spring (MVC = Model, View, Controller). This said, models are used together with "views".
What are these views? Views can be though as "html pages that are generated by our backend framework (Spring in our case) with some variable data in some parts of the html page".
So we have the model, which is an entity containing the data do be "injected" into the view.
There are several "view" libraries that you can work with Spring: among which, JSP, Thymeleaf, Mustache and others.
For example, let us assume we are using Thymeleaf (they are all similar. What's more, Spring does not even know, except for JSP, with which view libraries he is working with. All the models are served through the Servlet of Spring. This means that the Spring code will be the same for all these view libraries. The only thing you need to change is the syntax of such html pages, which are located in resources/static/templates)
resources/static/templates //All our view web pages are here
A Controller takes care of the routes. Let's say for example we have our site hosted on localhost:8080. We want a route (URL) showing us the students. Let us say that this is available at localhost:8080/students. The controller that will do this is StudentController:
#Controller //Not #RestController
public class StudentController {
#GetMapping(/students)
public String getStudentView() {
return "student";
}
}
What this code does, is saying that, if we are going to
localhost:8080/students
then the method getStudentView() is called. But notice it should return a String. However, when working with a view library, and the controller is annotated with #Controller (and not #RestController), what spring does is looking for an html view page with the name of the String that the method returns, in our case it will look for the view at
/resources/static/templates/student.html
This is good enough for static pages without data. However, if we need a dynamic page with some data, Spring offers another big advantage: the method above getStudentView(), will also pass, under the hood, a model to our view "student.html". Our model will contain data that we can access in the file "student.html" using the specific syntax from our view library. E.g., with thymeleaf:
<div th:text="${attribute1}"> </div>
This will access the attribute "attribute1" of our model.
We can pass different data through our model. This is done by assigning it various attributes. There are different ways of assigning attributes, with #ModelAttribute:
#Controller //Not #RestController
public class StudentController {
#ModelAttribute(name = "attribute1")
public int assignAttribute1() {
return 123454321
} // Think it as "model.attribute1 = 123454321"
#GetMapping(/students)
public String getStudentView() {
return "student";
}
}
The code above will assign to the model (created under the hood), an attribute with name "attribute1" (think it as of a key), with value 12354321. Something like "model.attribute1 = 123454321".
Finally, the model is passed to the view when we go to the url
localhost:8080/students
Notice: all the methods annotated with #ModelAttribute are invoked before a view is returned. The model, once all the attributes are created, is passed to our view. simply put, after the method getStudentView() is called, all the method with #ModelAttribute are called.
This being said, the html code written above, will be viewed from the browser as:
<div> 123454321 </div> // th:text is a command of
//THymeleaf, and says to substitute the text
// between the tags with the attribute "attribute1"
// of our model passed to this view.
This is the basic usage of #ModelAttribute.
There is also another important use case:
The model might be needed in the opposite direction: i.e., from the view to the controller. In the case described above, the model is passed from the controller to the view. However, let us say that the user, from our html page, sends back some data. We can catch it with out model attributes, #ModelAttribute. This has already been described by others

Related

How can I get default value using #ModelAttribute in Spring MVC? [duplicate]

What is the purpose and usage of #ModelAttribute in Spring MVC?
#ModelAttribute refers to a property of the Model object (the M in MVC ;)
so let's say we have a form with a form backing object that is called "Person"
Then you can have Spring MVC supply this object to a Controller method by using the #ModelAttribute annotation:
public String processForm(#ModelAttribute("person") Person person){
person.getStuff();
}
On the other hand the annotation is used to define objects which should be part of a Model.
So if you want to have a Person object referenced in the Model you can use the following method:
#ModelAttribute("person")
public Person getPerson(){
return new Person();
}
This annotated method will allow access to the Person object in your View, since it gets automatically added to the Models by Spring.
See "Using #ModelAttribute".
I know this is an old thread, but I thought I throw my hat in the ring and see if I can muddy the water a little bit more :)
I found my initial struggle to understand #ModelAttribute was a result of Spring's decision to combine several annotations into one. It became clearer once I split it into several smaller annotations:
For parameter annotations, think of #ModelAttribute as the equivalent of #Autowired + #Qualifier i.e. it tries to retrieve a bean with the given name from the Spring managed model. If the named bean is not found, instead of throwing an error or returning null, it implicitly takes on the role of #Bean i.e. Create a new instance using the default constructor and add the bean to the model.
For method annotations, think of #ModelAttribute as the equivalent of #Bean + #Before, i.e. it puts the bean constructed by user's code in the model and it's always called before a request handling method.
Figuratively, I see #ModelAttribute as the following (please don't take it literally!!):
#Bean("person")
#Before
public Person createPerson(){
return new Person();
}
#RequestMapping(...)
public xxx handlePersonRequest( (#Autowired #Qualifier("person") | #Bean("person")) Person person, xxx){
...
}
As you can see, Spring made the right decision to make #ModelAttribute an all-encompassing annotation; no one wants to see an annotation smorgasbord.
So I will try to explain it in simpler way. Let's have:
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
As described in the Spring MVC documentation - the #ModelAttribute annotation can be used on methods or on method arguments. And of course we can have both use at the same time in one controller.
1.Method annotation
#ModelAttribute("cities")
public List<String> checkOptions(){
return new Arrays.asList(new[]{"Sofia","Pleven","Ruse"});//and so on
}
Purpose of such method is to add attribute in the model. So in our case cities key will have the list new Arrays.asList(new[]{"Sofia","Pleven","Ruse"}) as value in the Model (you can think of Model as map(key:value)). #ModelAttribute methods in a controller are invoked before #RequestMapping methods, within the same controller.
Here we want to add to the Model common information which will be used in the form to display to the user. For example it can be used to fill a HTML select:
2.Method argument
public String findPerson(#ModelAttriute(value="person") Person person) {
//..Some logic with person
return "person.jsp";
}
An #ModelAttribute on a method argument indicates the argument should be retrieved from the model. So in this case we expect that we have in the Model person object as key and we want to get its value and put it to the method argument Person person. If such does not exists or (sometimes you misspell the (value="persson")) then Spring will not find it in the Model and will create empty Person object using its defaults. Then will take the request parameters and try to data bind them in the Person object using their names.
name="Dmitrij"&countries=Lesoto&sponsor.organization="SilkRoad"&authorizedFunds=&authorizedHours=&
So we have name and it will be bind to Person.name using setName(String name). So in
//..Some logic with person
we have access to this filled name with value "Dimitrij".
Of course Spring can bind more complex objects like Lists, Maps, List of Sets of Maps and so on but behind the scene it makes the data binding magic.
We can have at the same time model annotated method and request method handler with #ModelAttribute in the arguments. Then we have to union the rules.
Of course we have tons of different situations - #ModelAttribute methods can also be defined in an #ControllerAdvice and so on...
For my style, I always use #ModelAttribute to catch object from spring form jsp. for example, I design form on jsp page, that form exist with commandName
<form:form commandName="Book" action="" methon="post">
<form:input type="text" path="title"></form:input>
</form:form>
and I catch the object on controller with follow code
public String controllerPost(#ModelAttribute("Book") Book book)
and every field name of book must be match with path in sub-element of form
I know I am late to the party, but I'll quote like they say,
"better be late than never". So let us get going,
Everybody has their own ways to explain things, let me try to sum it up and simple it up for you in a few steps with an example;
Suppose you have a simple form, form.jsp:
<form:form action="processForm" modelAttribute="student">
First Name : <form:input path="firstName" />
<br/><br/>
Last Name : <form:input path="lastName" />
<br/><br/>
<input type="submit" value="submit"/>
</form:form>
<form:input path="firstName" /> <form:input path="lastName" /> These are the fields/properties in the Student class. When the form is called/initialized their getters are invoked. On form submit their setters are invoked, and their values are transferred in the bean that was indicated with modelAttribute="student" in the form tag.
We have StudentController that includes the following methods:
#RequestMapping("/showForm")
// `Model` is used to pass data between controllers and views
public String showForm(Model theModel) {
// attribute name, value
theModel.addAttribute("student", new Student());
return "form";
}
#RequestMapping("/processForm")
public String processForm(#ModelAttribute("student") Student theStudent) {
System.out.println("theStudent :"+ theStudent.getLastName());
return "form-details";
}
//#ModelAttribute("student") Student theStudent
//Spring automatically populates the object data with form data
//all behind the scenes
Now finally we have a form-details.jsp:
<b>Student Information</b>
${student.firstName}
${student.lastName}
So back to the question What is #ModelAttribute in Spring MVC?
A sample definition from the source for you,
http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation
The #ModelAttribute is an annotation that binds a method parameter or method return value to a named model attribute and then exposes it to a web view.
What actually happens is it gets all the values of your form those were submitted by it and then holds them for you to bind or assign them to the object. It works like the #RequestParameter where we only get a parameter and assign the value to some method argument.
The difference is that #ModelAttribute holds all form data rather than a single parameter. It creates a bean for you which holds the data submitted in the form.
To recap the whole thing:
Step 1:
A request is sent and our method showForm() runs and a model, a temporary bean, is set with the name student and forwarded to the form:
theModel.addAttribute("student", new Student());
Step 2:
Form attribute modelAttribute="student" defines that on form submission the model will update the student and will hold all parameters of the form.
Step 3:
On form submission the processForm() method is invoked with parameter #ModelAttribute("student") Student theStudent: the values being hold in the form with modelAttribute="student" were fetched and assigned to the fields in the Student object.
Step 4:
And then we use it as we bid, just like showing it on the page etc like I did
I hope it helps you to understand the concept. Thanks
Take any web application whether it is Gmail or Facebook or Instagram or any other web application, it's all about exchanging data or information between the end user and the application or the UI and the back end application. Even in Spring MVC world there are two ways to exchange data:
from the Controller to the UI, and
from the UI to the Controller.
What we are interested here is how the data is communicated from the UI to Controller. This can also be done in 2 ways:
Using an HTML Form
Using Query Parameters.
Using an HTML Form:
Consider the below scenario,
When we submit the form data from the web browser, we can access that data in our Controller class as an object. When we submit an HTML form, the Spring Container does four things. It will,
first read all the data that is submitted that comes in the request using the request.getParameter method.
once it reads them, it will convert them into the appropriate Java type using integer.parseInt, double.parseDouble and all the other parse methods that are available based on the data type of the data.
once parsed, it will create a object of the model class that we created. For example, in this scenario, it is the user information that is being submitted and we create a class called User, which the Container will create an object of and it will set all the values that come in automatically into that object.
it will then handover that object by setting the values to the Controller.
To get this whole thing to work, we'll have to follow certain steps.
We first need to define a model class, like User, in which the number of fields should exactly match the number of fields in the HTML form. Also, the names that we use in the HTML form should match the names that we have in the Java class. These two are very important. Names should match, the number of fields in the form should match the number of fields in the class that we create. Once we do that, the Container will automatically read the data that comes in, creates an object of this model, sets the values and it hands it over to the Controller. To read those values inside the Controller, we use the #ModelAttribute annotation on the method parameters. When we create methods in the Controller, we are going to use the #ModelAttribute and add a parameter to it which will automatically have this object given by the Container.
Here is an example code for registering an user:
#RequestMapping(value = "registerUser", method = RequestMethod.POST)
public String registerUser(#ModelAttribute("user") User user, ModelMap model) {
model.addAttribute("user", user);
return "regResult";
}
Hope this diagrammatic explanation helped!
#ModelAttribute can be used as the method arguments / parameter or before the method declaration.
The primary objective of this annotation to bind the request parameters or form fields to an model object
Ref. http://www.javabeat.net/modelattribute-spring-mvc/
This is used for data binding purposes in Spring MVC. Let you have a jsp having a form element in it e.g
on JSP
<form:form action="test-example" method="POST" commandName="testModelAttribute"> </form:form>
(Spring Form method, Simple form element can also be used)
On Controller Side
#RequestMapping(value = "/test-example", method = RequestMethod.POST)
public ModelAndView testExample(#ModelAttribute("testModelAttribute") TestModel testModel, Map<String, Object> map,...) {
}
Now when you will submit the form the form fields values will be available to you.
Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view.
public String add(#ModelAttribute("specified") Model model) {
...
}
#ModelAttribute will create a attribute with the name specified by you (#ModelAttribute("Testing") Test test) as Testing in the given example ,Test being the bean test being the reference to the bean and Testing will be available in model so that you can further use it on jsp pages for retrieval of values that you stored in you ModelAttribute.
#ModelAttribute simply binds the value from jsp fields to Pojo calss to perform our logic in controller class. If you are familiar with struts, then this is like populating the formbean object upon submission.
The ModelAttribute annotation is used as part of a Spring MVC Web application and can be used in two scenarios.
First of all, it can be used to inject data into a pre-JSP load model. This is especially useful in ensuring that a JSP is required to display all the data itself. An injection is obtained by connecting one method to the model.
Second, it can be used to read data from an existing model and assign it to the parameters of the coach's method.
refrence https://dzone.com/articles/using-spring-mvc%E2%80%99s
At the Method Level
1.When the annotation is used at the method level it indicates the purpose of that
method is to add one or more model attributes
#ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("india", "india");
}
At the Method Argument
1. When used as a method argument, it indicates the argument should be retrieved from the model. When not present and should be first instantiated and then added to the model and once present in the model, the arguments fields should be populated from all request parameters that have matching names So, it binds the form data with a bean.
#RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(#ModelAttribute("employee") Employee employee) {
return "employeeView";
}
First of all, Models are used in MVC Spring (MVC = Model, View, Controller). This said, models are used together with "views".
What are these views? Views can be though as "html pages that are generated by our backend framework (Spring in our case) with some variable data in some parts of the html page".
So we have the model, which is an entity containing the data do be "injected" into the view.
There are several "view" libraries that you can work with Spring: among which, JSP, Thymeleaf, Mustache and others.
For example, let us assume we are using Thymeleaf (they are all similar. What's more, Spring does not even know, except for JSP, with which view libraries he is working with. All the models are served through the Servlet of Spring. This means that the Spring code will be the same for all these view libraries. The only thing you need to change is the syntax of such html pages, which are located in resources/static/templates)
resources/static/templates //All our view web pages are here
A Controller takes care of the routes. Let's say for example we have our site hosted on localhost:8080. We want a route (URL) showing us the students. Let us say that this is available at localhost:8080/students. The controller that will do this is StudentController:
#Controller //Not #RestController
public class StudentController {
#GetMapping(/students)
public String getStudentView() {
return "student";
}
}
What this code does, is saying that, if we are going to
localhost:8080/students
then the method getStudentView() is called. But notice it should return a String. However, when working with a view library, and the controller is annotated with #Controller (and not #RestController), what spring does is looking for an html view page with the name of the String that the method returns, in our case it will look for the view at
/resources/static/templates/student.html
This is good enough for static pages without data. However, if we need a dynamic page with some data, Spring offers another big advantage: the method above getStudentView(), will also pass, under the hood, a model to our view "student.html". Our model will contain data that we can access in the file "student.html" using the specific syntax from our view library. E.g., with thymeleaf:
<div th:text="${attribute1}"> </div>
This will access the attribute "attribute1" of our model.
We can pass different data through our model. This is done by assigning it various attributes. There are different ways of assigning attributes, with #ModelAttribute:
#Controller //Not #RestController
public class StudentController {
#ModelAttribute(name = "attribute1")
public int assignAttribute1() {
return 123454321
} // Think it as "model.attribute1 = 123454321"
#GetMapping(/students)
public String getStudentView() {
return "student";
}
}
The code above will assign to the model (created under the hood), an attribute with name "attribute1" (think it as of a key), with value 12354321. Something like "model.attribute1 = 123454321".
Finally, the model is passed to the view when we go to the url
localhost:8080/students
Notice: all the methods annotated with #ModelAttribute are invoked before a view is returned. The model, once all the attributes are created, is passed to our view. simply put, after the method getStudentView() is called, all the method with #ModelAttribute are called.
This being said, the html code written above, will be viewed from the browser as:
<div> 123454321 </div> // th:text is a command of
//THymeleaf, and says to substitute the text
// between the tags with the attribute "attribute1"
// of our model passed to this view.
This is the basic usage of #ModelAttribute.
There is also another important use case:
The model might be needed in the opposite direction: i.e., from the view to the controller. In the case described above, the model is passed from the controller to the view. However, let us say that the user, from our html page, sends back some data. We can catch it with out model attributes, #ModelAttribute. This has already been described by others

Spring Roo: How to get the attributes of the model passed to the view

I have created a project using Spring Roo. I have a User entity (MODEL), which I pass to a .jspx file (VIEW). I would like to display the User information such as name, address and other attributes that my User class has.
This is the code in the controller that passes the Model to the View:
#RequestMapping(value = "/{id}", produces = "text/html")
public String UserRoleController.show(#PathVariable("id") Long id, Model uiModel) {
uiModel.addAttribute("userrole", UserRole.findUserRole(id));
return "userroles/account";
}
I know that in a jspx file I can get the information passed by using ${"userrole"}, but how do I get the actual attributes of the object?
Very simple, in your JSP just do :
${userrole.yourAttribute}
No need to use quotes or whatever when you are inside a ${}.

How to pass #RequestParam and #ModelAttribute in one form

I would like to mix #RequestParam and #ModelAttribute in one spring form and controller.
Things that I do in my controller are as follows:
#RequestMapping("/user/edit/{userId}")
public ModelAndView editUser(#PathVariable String userId,
#ModelAttribute User user, BindingResult bindingResult,
#RequestParam Set<String> groups) {
if(bindingResults.hasErrors() {
//return back to form and correct errors
} else {
//save data and get out of form
}
}
There are simple User bean (id, firstName, lastName, etc) but without "groups" property.
There is also simple Group bean (id, name, description) but without any connection with User.
So on the logical level User and Group are totally separeted.
In my form, when editing User, there is a html SELECT element that contains ids of all groups. You can select multiple ids together with filling User data and send it to controller.
Until now, everything works pretty well. I get #ModelAttibute User properly filled. I also get #RequestParam Set[String] groups filled with selected ids (Strings).
Now I would like to do something more. I need to write something that instead of #RequestParam Set[String] groups will give me #RequestParam Set[Group] groups. Of course I can convert it directly in my controller method editUser(...) but it's not a nice solution. So I decided to write a custom #InitBinder method that will do it for me nicely and smoothly.
And tere the problem comes.
I wrote the initBinder as follows:
[...]
webDataBinder.registerCustomEditor(Set.class, "groups", new CustomCollectionEditor(Set.class) {
#Override
protected Object convertElement(Object element) {
if (element instanceof GroupName) {
return element;
}
if (element instanceof String) {
Group group = userCatalog.loadGroup((String) element);
return group.getGroupName();
}
return null;
}
});
[...]
The problem is that there is absolutely no way to call this method. I put inside that some "debugging" System.out.println(...) but it doesn't print anything.
My question is: how to write a correct InitBinder that will be invoked in response to Strings array from html OPTION element and convert it to my Set of Users.
I changed some brackets to this [ and ] because it wasn't displayed.
Thank you for help.
meanwhile I came across on this topic: Custom property editors do not work for request parameters in Spring MVC?
and I think this is a key to the solution. In fact, as javadocs says, "field" argument is necessary only when using ModelAttibute (or form backing object which is the same...), but not for RequestParam. So is there any solution to use InitBinder together with RequestParam? Or I need to write a direct method in controller that converts ids to Set of Group objects?
Try registering your custom editor just against the Set.class type and leaving out the field name to see if that works.
webDataBinder.registerCustomEditor(Set.class, new CustomCol...
I have a suspicion that the field parameter denotes the property name of a ModelAttribute and not the request parameter name.
Alternatively, you could use a wrapper view model and use a second ModelAttribute parameter,
class GroupsViewModel {
private List<Group> groups
...
}

Spring MVC binding to wrong fields

I have a controller with 2 methods that return related objects via the #ModelAttribute annotation:
#ModelAttribute("site")
public Site getSite(){
.....
return site;
}
#ModelAttribute("document")
public Document getDocument(){
.....
return document;
}
These objects are related to each other with one Site having many Documents. This relationship is mapped in JPA. Both of these objects contain a field with the same name, called "urlAlias". This field is edited on a page using the following freemarker markup:
<#spring.bind "document" />
....
<#spring.formInput "document.urlAlias" />
When I submit the form to the controller, I retrieve the document object using the following syntax:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView create(#ModelAttribute("document") #Valid Document document, BindingResult documentResult,
#ModelAttribute("site") Site site, Model model){
...Do Stuff...
}
It appears that any value that I enter into the Document's urlAlias field has also been set in the Site object, even though I only edited the value of the field in the Document object.
I'm perplexed as to what is going on here. Am I doing something untoward by mapping more than one ModelAttribute in the same controller? Are there any other likely causes of this behaviour?
It would appear that the problem is the site parameter in the create() method in my controller:
#ModelAttribute("site") Site site
Removing that stops Spring binding to fields in that object. For future googlers, I get hold of the Site object within the create() method using the code below instead:
if (!model.containsAttribute("site")) {
throw new IllegalArgumentException("Model must contain site attribute.");
}
Site site = (Site) model.asMap().get("site");
From this it would appear that it is fine to declare more than one ModelAttribute in a controller, but only one can be used at a time as a parameter in a method.

spring mvc 3 - SessionAttributes doesn't seem to be working

I have tried and tried but can't figure out what is going on here.
I have a simple controller annotated using #Controller
I also have annotation for #SessionAttributes
I handle a GET request and put an object into the model.
When I get back the POST from the form, I only get back what the user has populated. I'm not getting back the complete object.
I'm new to SessionAttributes but I thought this preserved the whole object and when the object was read back in the method using #ModelAttribute, it would be merged the object (i.e. the object that the form changed). However, I'm not seeing this behavior.
Any help would be much appreciated.
Here is the relevant pieces from the code:
#Controller
#RequestMapping("/user")
#SessionAttributes("user")
public class UserController
{
// ...
#RequestMapping(value = "/{login}", method = RequestMethod.GET)
public String profile(Model model, #PathVariable("login") String login)
{
// ...
model.addAttribute("user", user);
// ...
}
#RequestMapping(value="/{login}", method = RequestMethod.POST)
public String saveProfile(#ModelAttribute("user") #Valid User user, BindingResult result, SessionStatus status)
{
if (result.hasErrors())
{
return "user/index";
}
// ...
status.setComplete();
return "redirect:/user/"+user.getLogin();
}
Do you see anything that I may have missed? I have spent almost a day trying to figure this out and just can't. Any help would be much appreciated.
Update: I figured out what the issue was. Answer posted below.
I figured out what was going after much laboring. I hope this saves somebody else the time.
The underlying problem here was twofold:
The object being saved in the session was decorated with some aspectj notations. Because of this the attribute values for the object were only returned by the appropriate get accessors.
I had hibernate validation in place (note the #Valid annotation in the method that handles the POST). The validator annotations were directly on each field (as below):
#NotNull
private String name;
Here is how I fixed it.
For testing purposes only, I removed the #Valid and noticed that even though the fields themselves seem to be NULL, we were saving the correct data in our backend store. This is what clued me into the root cause of this issue.
I figured the validator annotations were causinI moved the validator notation to get methods. So the code changed as follows:
private String name;
#NotNull
public String getName() {...}
I put the #Valid annotation back in and verified that the validation was no longer failing.
Hope it helps someone out there and save them a day of work. :)
I would not expect that spring merges the properties form session and form. You should separate the user that is submitted by the form, and the user from the session.
I had the same question as Azeem, and since he did not explicitly confirm that sessionattribute can be used to "merge" the original form backing object with the changes posted in the submit, I wanted to point out that yes, the changes from the form submit do get merged into the original form backing object.
There can be some issues with this approach as pointed out in
Spring MVC 3.0: How do I bind to a persistent object
but this approach is very helpful when you have a complex form backing object but you are only allowing the user to update a few of the object graph members in the form and not using hidden fields to maintain the remainder of the complex object in form elements.
When this approach is used without the use of the #SessionAttributes("xxx") annotation on the class, the returned form backing object is basically null except for those members specifically submitted by the form. This can make persisting the updated objects very difficult because you would have to combine the new updates into the original object yourself. But with use of the sessionattribute, the full updated form backing object provided after the submital makes persisting the object graph much easier.

Categories

Resources