Mark
Mark

Reputation: 11018

How to map @requestBody to a specific initBinder method?

I have code that looks like this:

Controller

public String doStuff(@Valid @RequestBody MyClass obj, BindingResult result) {
  ... 
}

Validation

@InitBinder
public void initBinder(WebDataBinder binder, HttpServletRequest request) {
  binder.setValidator(new MyValidator());
}

The problem is that I don't know how to "hook up" the obj param with the specific initBinder method I need to run to automagically validate obj with my custom Validator class. I need some way to have a specific @InitBinder method run after the obj param is bound to the request body.

Also, I have to use @RequestBody since the controller method is taking in a JSON payload in the request body.

Upvotes: 3

Views: 2358

Answers (2)

rougou
rougou

Reputation: 1216

If you only have a single parameter type, it is sufficient to have the InitBinder in the same controller class as rorschach mentioned. Otherwise, you can specify the class name of the parameter (starting with lowercase letter) you want to bind to:

@InitBinder("myClass")
public void initBinder(WebDataBinder binder, HttpServletRequest request) {
  binder.setValidator(new MyValidator());
}
public String doStuff(@Valid @RequestBody MyClass obj, BindingResult result) {
  ... 
}
@InitBinder("myClass2")
public void initBinder2(WebDataBinder binder, HttpServletRequest request) {
  binder.setValidator(new MyValidator2());
}
public String doStuff2(@Valid @RequestBody MyClass2 obj, BindingResult result) {
  ... 
}

I'm not sure where exactly in the documentation it explains this, but the javadoc for InitBinder does say the following:

Specifying model attribute names or request parameter names here restricts the init-binder method to those specific attributes/parameters

So I guess by default the parameter name is the name of the class starting with a lowercase letter.

Upvotes: 1

rorschach
rorschach

Reputation: 2947

I think it should be sufficient to have the @InitBinder method in the same Controller class as your doStuff() method.

Alternatively, you can also create a custom annotation for MyValidator and apply it on the class level in MyClass instead of using @InitBinder. This also has the added benefit of being initiated and run on any method call where one of the arguments is @Valid MyClass obj.

Upvotes: 1

Related Questions