Using @ModelAttribute annotation in Spring MVC
Background
I developed a chat application with Spring MVC
, and here are the codes in the ChatController
Class and the chat.html
page:
![](controller.png)
![](html.png)
Problem
Notice that I used the newChatForm
identifier in th:object
present in the chat.html
page to name the ChatForm
parameter both in the getChatPage
and addChat
method.
But when I removed the @ModelAttribute("newChatForm")
in one of those methods, I got the error below:
![](error.png)
What’s wrong
Since I included th:object
in the chat.html
page, and so for the mapping to be done, a ChatForm
object needs to be included in the Spring Container
to be used by Spring MVC
to map the form data.Spring MVC
will check in the Spring Container
if there is any instance with the name similar to th:object
. If there is one it ends up using that instance in the mapping.
But when I only put ChatForm newChatForm
in the method parameter, I am telling Spring
that this parameter must be instantiated (with the default name chatForm
, which is the camelCase pattern of ChatForm
), because it will be used in the method as well as the Model
. The ChatForm
is only included in the Spring Container
not being included by the Model
in the chat.html
page.
Since the default name chatForm
is different from the newChatForm
identifier in th:object
present in the chat.html
, Spring MVC
can’t find any instance to map the form data, which causes the error I received.
However, when I use @ModelAttribute("newChatForm")
, I am indicating to Spring
that besides instantiating the ChatForm
, this ChatForm
must be included in the page through the newChatForm
identifier, since this inclusion is made through the Model
. So no error is thrown.
So, the inclusion of the @ModelAttribute
depends on the identifiers being used, if both are equal, its inclusion is not necessary, otherwise, we need it so that a mapping error does not occur.
Solution
There are two ways to solve this problem:
Use
chatForm
identifier both inchat.html
and in theChatController
method parameterchat.html 1
2
3<form th:action="@{'/chat'}" th:object="${chatForm}" action="#" method="POST">
// nothing changes
</form>ChatController.java 1
2
3
4
5
6
7
8
9
public String getChatPage(ChatForm chatForm, Model model) {
// nothing changes
}
public String addChat(ChatForm chatForm, Model model) {
// change variable name from "newChatForm" to "chatForm"
}This way
Spring MVC
directly uses theChatForm
instance in theSpring Container
for mapping, so we don’t need to use@ModelAttribute
.However, this approach requires that other developers have some knowledge of how
Spring
works under the hood, otherwise they will probably delete theChatForm
thinking that this parameter is not doing anything.Create the
getChatForm
method to return the instanceEvery time the
"/chat"
endpoint is triggered,Spring
will automatically assign aChatForm
instance to thechat.html
page.For improving the readability of the code by showing more clearly the process of assigning the instance by
Spring
,We can create the
getChatForm
method which will be responsible for including the object in theSpring Container
and which can be used bySpring MVC
for mapping:ChatController.java 1
2
3
4
public ChatForm getChatForm {
return new ChatForm();
}This way we can remove the
@ModelAttribute("newChatForm")
from both methods and theChatForm
from thegetChatPage
method:ChatController.java 1
2
3
4
5
6
7
8
9
public String getChatPage(Model model) {
// nothing changes
}
public String addChat(ChatForm newChatForm, Model model) {
// nothing changes
}
References
Difference between using and not using @modelAttribute in method parameter
What is the meaning of @ModelAttribute annotation at method argument level?
Using @ModelAttribute annotation in Spring MVC