0

I want to override this behaviour from this Spring class:

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
    ...
    @Override
    protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
            Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
            ...
            if (arg == null && checkRequired(parameter)) {
                throw new HttpMessageNotReadableException("Required request body is missing: " +
                    parameter.getExecutable().toGenericString(), inputMessage);
            }
    ...
}

This method handles the error when @ReponseBody is null from a @Controller. I tried to make my own CustomBodyMethodProcessor extending from RequestResponseBodyMethodProcessor like this:

public class CustomBodyMethodProcessor extends RequestResponseBodyMethodProcessor {

    public CustomBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    @Override
    protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
                                                   Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        Assert.state(servletRequest != null, "No HttpServletRequest");
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

        Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
        if (arg == null && checkRequired(parameter)) {
            //I want to change this....
            throw new HttpMessageNotReadableException("Required request body is missing: " +
                    parameter.getExecutable().toGenericString(), inputMessage);
        }
        return arg;
    }

}

So, to add the new CustomBodyMethodProcessor I did :

@Configuration
@EnableWebMvc
public class WebMvcConfig implements  WebMvcConfigurer {

    @Autowired
    List<HttpMessageConverter<?>> converters;


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        WebMvcConfigurer.super.addArgumentResolvers(resolvers);
        resolvers.add(new CustomBodyMethodProcessor(converters));

    }

}

But this not works. When I debug, always stops in readWithMessageConverters method from RequestResponseBodyMethodProcessor and not in my overrided method from CustomBodyMethodProcessor

I appreciate any help you can provide me !!

Thanks

Miguel Cabanes
  • 103
  • 2
  • 10
  • 1
    What happens if you add yours’ earlier in the list (`resolvers.add(new …, 0);`)? Or remove the other one (`resolvers.removeIf(i -> i instanceof RequestResponseBodyMethodProcessor);`) before adding yours’? – BeUndead May 28 '21 at 22:42
  • Hi! `resolvers` is empty, no instances of `RequestResponseBodyMethodProcessor` inside. Add mine with index 0 and no results... Thanks! – Miguel Cabanes May 28 '21 at 23:00
  • 1
    Your answer @BeUndead takes me to the right path... https://stackoverflow.com/a/19847526/4267653 – Miguel Cabanes May 29 '21 at 00:19

1 Answers1

0

Found the solution.

    @Autowired
    private RequestMappingHandlerAdapter adapter;

    @PostConstruct
    public void prioritizeCustomArgumentMethodHandlers () {
        List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(adapter.getArgumentResolvers ());
        List<HandlerMethodArgumentResolver> customResolvers = adapter.getCustomArgumentResolvers();
        argumentResolvers.removeAll(customResolvers);
        argumentResolvers.addAll (0, customResolvers);
        adapter.setArgumentResolvers (argumentResolvers);
    }

My CustomBodyMethodProcessor was added to the list of resolvers but original RequestResponseBodyMethodProcessor has precedence so CustomBodyMethodProcessor is never invoked.

The solution was to delete from resolvers my CustomBodyMethodProcessor, give precedence and add it again to the list!

Thanks to this asnwer https://stackoverflow.com/a/19847526/4267653 and to @BeUndead for the clue !

Miguel Cabanes
  • 103
  • 2
  • 10
  • No idea if it works in this case, but most spring collections support `implements Ordered`, or `@Order` on the class. So you could try `@Order(Ordered.HIGHEST_PRECEDENCE)` on your custom class and it may work without this step. Glad you got it working though. – BeUndead May 30 '21 at 01:54