Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

replacing AnnotationMethodHandlerAdapter with RequestMappingHandlerAdapter issue

Tags:

spring-mvc

I recently upgraded to spring 3.2 and noticed that AnnotationMethodHandlerAdapter had been deprecated in favor of RequestMappingHandlerAdapter. So I reconfigured to use the new class, complete with a custom MessageConverter I need. All fine and good.

However, when attempting to hit a URL supported by an annotated Controller, I'm getting an error:

 [java] javax.servlet.ServletException: No adapter for handler [my.company.TagController@1c2e7808]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
 [java]     at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1128)
 [java]     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:903)
 [java]     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)

When debugging the dispatcher, and in particular, the Dispatcher.getHandlerAdapter() method, it's finding my HandlerAdapter, but the AbstractHandlerMethodAdapter.supports() that is invoked wants a MethodHandler:

public final boolean supports(Object handler) {
  return handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler);
}

and the controller is not a HandlerMethod. The AnnotatedMethodHandlerAdapter's support method is.. well, different (and works still!)

public boolean supports(Object handler) {
  return getMethodResolver(handler).hasHandlerMethods();
}

So I apparently cannot simply upgrade to the new class... I'm missing some additional configuration, but the documentation isn't really helping me out. Any ideas?

Thanks.

like image 251
ticktock Avatar asked Jul 03 '13 00:07

ticktock


People also ask

What is the use of Requestmappinghandleradapter?

The RequestMappingHandlerMapping is used to maintain the mapping of the request URI to the handler. Once the handler is obtained, the DispatcherServlet dispatches the request to the appropriate handler adapter, which then invokes the handlerMethod().

What is the use of Defaultannotationhandlermapping in Spring?

The AnnotationMethodHandlerAdapter is responsible for processing annotated handler methods, as mapped by this HandlerMapping. For RequestMapping at the type level, specific HandlerAdapters such as SimpleControllerHandlerAdapter apply. Add URLs and/or URL patterns for the given path.


2 Answers

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
  @Override
  protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
    return new XXXXRequestMappingHandlerAdapter();
  }
}
like image 191
lemonzone2010 Avatar answered Nov 27 '22 18:11

lemonzone2010


So as it turns out, simple switching the bean definition doesn't work due to the fact that the RequestMappingHandlerAdapter is depending on a whole host of entities being created and configured. Spring, by default, is using a WebMvcConfigurationSupport entity to do all this default configuration, but simply creating my own bean version doesn't help because spring creates its own.

My approach ended up being something along the lines of below, where I left basically all of the configuration up to spring's default, but then added my own converter. The only drawback is that it's switching xml configuration to javaconfig, but in my case, it's ok. There's an article here that describes something similar.

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

  @Bean
  public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
    RequestMappingHandlerAdapter handlerAdapter = super.requestMappingHandlerAdapter();
    handlerAdapter.getMessageConverters().add(0, getProtobufJsonMessageConverter());
    return handlerAdapter;
  }
like image 24
ticktock Avatar answered Nov 27 '22 16:11

ticktock