-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Brice Roncace opened SPR-16083 and commented
Given this test controller (and java bean):
@Controller
public class TestController {
public static class Bean {
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public String toString() {
return "Bean{" + "id=" + id + '}';
}
}
@ModelAttribute
public Bean prepareBean() {
return new Bean();
}
@ModelAttribute
public void prepareBean2(@ModelAttribute(binding=false) Bean bean) {
System.out.println("prepareBean2: " + bean);
}
@GetMapping("/bindTest")
public String editBean(@ModelAttribute(binding=true) Bean bean, BindingResult br) {
System.out.println("Inside editBean: " + bean);
System.out.println(br.getAllErrors());
return "index";
}
}
When exercising this controller with bindTest?id=1 no binding will occur because the prepareBean2 method disables binding for the bean model attribute even though a subsequent use of the @ModelAttribute in the editBean method expects binding to occur.
The unsatisfactory workarounds are to allow binding and insert an ignored BindingResult parameter in the prepareBean2 method so that if binding errors occur, they can be handled in the editBean method where they are expected:
@ModelAttribute
public Bean prepareBean() {
return new Bean();
}
@ModelAttribute
public void prepareBean2(@ModelAttribute Bean bean, BindingResult ignore) {
System.out.println("prepareBean2: " + bean);
}
@GetMapping("/bindTest")
public String editBean(@ModelAttribute Bean bean, BindingResult br) {
System.out.println("Inside editBean: " + bean);
System.out.println(br.getAllErrors());
return "index";
}
Or pull the bean out of the model to prevent binding in the prepareBean2 method:
@ModelAttribute
public Bean prepareBean() {
return new Bean();
}
@ModelAttribute
public void prepareBean2(Model m) {
Object bean = m.asMap().get("bean");
System.out.println("prepareBean2: " + bean);
}
@GetMapping("/bindTest")
public String editBean(@ModelAttribute Bean bean, BindingResult br) {
System.out.println("Inside editBean: " + bean);
System.out.println(br.getAllErrors());
return "login";
}
Note: in a real-world example these two @ModelAttribute annotated methods would not appear in the same class (e.g. @ControllerAdvice would apply the initial prepareBean method).
Issue Links:
- Prevent binding for @ModelAttribute [SPR-13402] #17982 Prevent binding for
@ModelAttribute
Referenced from: commits b0ae8f6, bec1fc1
Backported to: 4.3.13