Обработка исключений Spring 4: нет подходящего преобразователя для аргумента

Постановка задачи

Миграция на Spring 4 из Spring 3 вызывает некоторые исключения в потоке обработки исключений. Исключение говорит No suitable resolver for argument в классе org.springframework.web.method.support.InvocableHandlerMethod.

Поэтому всякий раз, когда возникает исключение, Spring пытается найти обработчик исключений, который он получает, но когда он пытается заполнить аргументы метода или обработчик исключений, он выдает следующее исключение.

Не удалось вызвать метод @ExceptionHandler:

  public org.springframework.web.servlet.ModelAndView  
       HelloController.handleCustomException(CustomGenericException, javax.servlet.http.HttpServletRequest, org.springframework.web.servlet.ModelAndView)

  java.lang.IllegalStateException: 
     No suitable resolver for argument [2] 
             [type=org.springframework.web.servlet.ModelAndView]

Детали метода обработчика:

Controller [HelloController]
Method [public org.springframework.web.servlet.ModelAndView  
        HelloController.handleCustomException(CustomGenericException,
            javax.servlet.http.HttpServletRequest,org.springframework.web.servlet.ModelAndView)]
        at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(
                     InvocableHandlerMethod.java:169)

В основном это происходит для переменной @CRequestParam("p") String p

Код

Контроллер

@RequestMapping(method = RequestMethod.GET, value="/exception2")
    public String getException1(ModelMap model, @CRequestParam("p") String p) {

        System.out.println("Exception 2 "+ p);
        throw new CustomGenericException("1","2");
    }

Обработчик исключений

@ExceptionHandler(CustomGenericException.class)
    public ModelAndView handleCustomException(CustomGenericException ex, 
            HttpServletRequest request, @CRequestParam("p") String p) {

            ModelAndView model = new ModelAndView("error/generic_error");
            model.addObject("exception", ex);
            System.out.println("CustomGenericException  ");
            return model;
    }

Аннотации

@Target( { ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CRequestParam {
    String value() default "";
}

Преобразователь параметров

public class CRequestparamResolver implements HandlerMethodArgumentResolver {


    @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
          CRequestParam requestParamAnnotation = 
          methodParameter.getParameterAnnotation(CRequestParam.class);
        if(requestParamAnnotation==null){
        return false;
        }
        return true;
        }

    @Override
    public Object resolveArgument(MethodParameter methodParameter,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
        WebDataBinderFactory binderFactory) throws Exception {

    CRequestParam requestParamAnnotation = methodParameter .getParameterAnnotation(CRequestParam.class);

    if (requestParamAnnotation != null) {
        String requestParamName = requestParamAnnotation.value();
        if (StringUtils.hasText(requestParamName)) {
        return webRequest.getParameter(requestParamName);
        }
    }
    return null;
  }

XML-конфигурация

<bean
        class="com.mkyong.common.resolver.AnnotationMethodHandlerAdapterConfigurer"
        init-method="init">
        <property name="customArgumentResolvers">
            <list>
                <bean class="com.mkyong.common.resolver.CRequestparamResolver" />
            </list>
        </property>
    </bean>

    <bean 
 class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
        <property name="customArgumentResolvers">
            <list>
                <bean class="com.mkyong.common.resolver.CRequestparamResolver" />
            </list>
        </property>
    </bean>

Исходный код

https://github.com/santoshjoshi/SpringMVC4


person Santosh Joshi    schedule 30.07.2014    source источник
comment
Я предполагаю, что вместо @CRequestParam вы имеете в виду @RequestParam   -  person geoand    schedule 30.07.2014
comment
@geo и его настраиваемый параметр запроса CRequestParam, для которого у нас есть CRequestparamResolver преобразователь.   -  person Santosh Joshi    schedule 30.07.2014
comment
@geo, и весь исходный код теперь зарегистрирован в https://github.com/santoshjoshi/SpringMVC4   -  person Santosh Joshi    schedule 30.07.2014
comment
Не могли бы вы опубликовать более полную трассировку стека?   -  person geoand    schedule 30.07.2014
comment
AFAIK RequestMappingHandlerAdapter не обрабатывает исключение, поэтому его преобразователи аргументов нельзя использовать. Посмотрите на ExceptionHandlerExceptionResolver.setArgumentResolvers(). Я никогда не использовал его сам, но он выглядит многообещающе.   -  person Bart    schedule 30.07.2014
comment
@geo и весь код исключения доступен по адресу https://gist.github.com/santoshjoshi/31701ec034839ead3c7d   -  person Santosh Joshi    schedule 30.07.2014


Ответы (2)


Решил проблему, передав пользовательские аргументы в самом запросе.

код, как показано ниже:

Контроллер

@RequestMapping(method = RequestMethod.GET, value = "/exception2")
public String getException1(ModelMap model, @CRequestParam("p") String p, HttpServletRequest request) {

  System.out.println("Exception 2 " + p);
  request.setAttribute("p", p);
  throw new CustomGenericException("1", "2");
}

Обработчик исключений

@ExceptionHandler(CustomGenericException.class)
public ModelAndView handleCustomException(CustomGenericException ex, HttpServletRequest request) {

  ModelAndView model2 = new ModelAndView("error/generic_error");
  model2.addObject("exception", ex);
  System.out.println(request.getAttribute("p"));
  System.out.println("CustomGenericException  ");
  return model2;

}

Полный исходный код доступен по адресу git.

person Santosh Joshi    schedule 04.08.2014

Решил проблему, предоставив реализацию WebApplicationInitializer

public class SpringDispatcherConfig implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext Contianer =   new AnnotationConfigWebApplicationContext();
    Contianer.register(SpringConfig.class);
    Contianer.setServletContext(servletContext);
    DispatcherServlet dispatcherServlet = new DispatcherServlet(Contianer);
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    Dynamic servlet = servletContext.addServlet("spring",dispatcherServlet);
    servlet.addMapping("/");
    servlet.setLoadOnStartup(1);

}
person Fakhri Satii Boto    schedule 30.01.2018