Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring RequestBodyAdvice not being triggered

Tags:

spring-mvc

I declared a @ControllerAdvice which implements RequestBodyAdvice. My problem that its not being triggered. I have a ResponseBodyAdvice in the same package, which is working as expected.

@RestControllerAdvice
public class RestPreProcessingAdvice implements RequestBodyAdvice {

  @Override
  public boolean supports(final MethodParameter methodParameter, final Type targetType,
      final Class<? extends HttpMessageConverter<?>> converterType) {
    return checkIfElegiable(...);
  }

  @Override
  public Object handleEmptyBody(final Object body, final HttpInputMessage inputMessage, final MethodParameter parameter,
      final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }

  @Override
  public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage, final MethodParameter parameter,
      final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
    return doSomeProcessing(...);
  }

  @Override
  public Object afterBodyRead(final Object body, final HttpInputMessage inputMessage, final MethodParameter parameter,
      final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) {
    return body;
  }
}

I debugged and am seeing that this @ControllerAdvice is being found in ControllerAdviceBean.findAnnotatedBeans(). But why its not triggered I couldn't find out so far.

I guess some other people are having the similar problems. See How to use RequestBodyAdvice and Spring RequestBodyAdvice is not picking up by the mock MVC frame work, how ever it is working for ResponseBodyAdvice.

like image 960
user871611 Avatar asked Jan 17 '17 08:01

user871611


2 Answers

In your controller method try annotating the method parameter with @RequestBody.

E.g.

@RestController
public class MyController{

   @RequestMapping(.......)
   public MyResponse greetings(@RequestBody MyRequest requestObject){
        //implementation
   }

}

RequestResponseBodyMethodProcessor class (and its base class AbstractMessageConverterMethodArgumentResolver) are responsible for invoking the various abstract methods (beforeBodyRead, afterBodyRead etc) of RequestBodyAdvice. RequestMappingHandlerAdapter would choose RequestResponseBodyMethodProcessor to process the request only if the controller method's arguement is annotated with @RequestBody. We can see this logic implemented in the supportsParameter method of RequestResponseBodyMethodProcessor.

I think an alternate way would be to create our own MethodProcessor by extending RequestResponseBodyMethodProcessor and overriding its supportsParameter method to put our own logic. I have not tested this, though.

like image 69
jacjos Avatar answered Nov 23 '22 23:11

jacjos


You should be able to use DelegatingWebMvcConfiguration to set the RequestBodyAdvice.

@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {

    public RequestBodyAdvice myRequestBodyAdvice(){
        return new MyRequestBodyAdvice();
    }


    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter adapter = 
super.requestMappingHandlerAdapter();
        adapter.setRequestBodyAdvice(Arrays.asList(myRequestBodyAdvice()));
        return adapter;
    }
}

See section 22.16.13 in Spring Framework Docs

like image 31
user2294382 Avatar answered Nov 23 '22 23:11

user2294382