About org.springframework.web.bind.annotation.ModelAttribute annotation of Spring Web MVC

Controller Following is a Controller to handle POST requests of HTTP form. @Controller @RequestMapping("/manage") public class PrivateController { @PostMapping("/new") public String saveCreateMessage(@Valid @ModelAttribute("message") MessageMvcDto message, BindingResult errors, Model model) { if (errors.hasErrors()) { model.addAttribute("isEdit", false); model.addAttribute("postHandler", "new"); return "private/message"; } MessageDto dto = new MessageDto(); dto.setPublishDate(message.getPublishDate()); dto.setRemoveDate(message.getRemoveDate()); dto.setDescription(message.getDescription()); dto.setOwner(this.getLoginName()); this.messageService.save(dto); return "redirect:/manage"; } // ... } Before executing saveCreateMessage() method, the framework will bind values sent by POST to MessageMvcDto instance, perform validation and build BindingResult instance. Then execute saveCreateMessage() and pass MessageMvcDto, BindingResult instance as parameter. Assume that validation failed and has an error, a template string is returned. Since parameter message is annotated with @ModelAttribute("message"), the binded MessageMvcDto and BindingResult instance will write into Model as follows. Key Value message MessageMvcDto instance org.springframework.validation.BindingResult.message BindingResult instance If annotated with @ModelAttribute (without name), will become the following. Key Value messageMvcDto MessageMvcDto instance org.springframework.validation.BindingResult.messageMvcDto BindingResult instance Rendering Values in the Model will become attributes of HttpServletRequest (but not in Session). WebEngineContext instance is built for Thymeleaf to lookup the value of expression. Using the following template [[#{save}]] [[#{cancel}]] #fields expression can be used within form tag with th:object only. When processing form tag, attribute th:object will save into HttpServletRequest attribute springBoundObjectExpression (i.e. "${message}"). When processing #fields expression, first lookup HttpServletRequest attribute springBoundObjectExpression, then prepend the result with org.springframework.validation.BindingResult. (i.e. org.springframework.validation.BindingResult.message) and lookup HttpServletRequest attribute again. Afterward a BindingResult instance is found (BindingResult is the child interface of Errors) and a related method is called. The reason why nothing happened on using #fields expression is not to set name on @ModelAttribute annotation.

Jan 18, 2025 - 14:52
About org.springframework.web.bind.annotation.ModelAttribute annotation of Spring Web MVC

Controller

Following is a Controller to handle POST requests of HTTP form.

@Controller
@RequestMapping("/manage")
public class PrivateController {

    @PostMapping("/new")
    public String saveCreateMessage(@Valid @ModelAttribute("message") MessageMvcDto message, BindingResult errors, Model model) {
        if (errors.hasErrors()) {
            model.addAttribute("isEdit", false);
            model.addAttribute("postHandler", "new");
            return "private/message";
        }

        MessageDto dto = new MessageDto();
        dto.setPublishDate(message.getPublishDate());
        dto.setRemoveDate(message.getRemoveDate());
        dto.setDescription(message.getDescription());
        dto.setOwner(this.getLoginName());
        this.messageService.save(dto);
        return "redirect:/manage";
    }

    // ...
}

Before executing saveCreateMessage() method, the framework will bind values sent by POST to MessageMvcDto instance, perform validation and build BindingResult instance.

Then execute saveCreateMessage() and pass MessageMvcDto, BindingResult instance as parameter. Assume that validation failed and has an error, a template string is returned.

Since parameter message is annotated with @ModelAttribute("message"), the binded MessageMvcDto and BindingResult instance will write into Model as follows.

Key Value
message MessageMvcDto instance
org.springframework.validation.BindingResult.message BindingResult instance

If annotated with @ModelAttribute (without name), will become the following.

Key Value
messageMvcDto MessageMvcDto instance
org.springframework.validation.BindingResult.messageMvcDto BindingResult instance

Rendering

Values in the Model will become attributes of HttpServletRequest (but not in Session). WebEngineContext instance is built for Thymeleaf to lookup the value of expression.

Using the following template


  

#fields expression can be used within form tag with th:object only.

When processing form tag, attribute th:object will save into HttpServletRequest attribute springBoundObjectExpression (i.e. "${message}").

When processing #fields expression, first lookup HttpServletRequest attribute springBoundObjectExpression, then prepend the result with org.springframework.validation.BindingResult. (i.e. org.springframework.validation.BindingResult.message) and lookup HttpServletRequest attribute again. Afterward a BindingResult instance is found (BindingResult is the child interface of Errors) and a related method is called.

The reason why nothing happened on using #fields expression is not to set name on @ModelAttribute annotation.