Spring MVC - 无法调用自定义ExceptionHandler

时间:2016-03-14 13:16:21

标签: java spring-mvc spring-boot

我在应用程序的服务器日志中收到一个奇怪的异常。向某个URL发出GET请求时发生异常。该URL具有以下格式 -

/some_list/{id}/some_method

处理程序的定义如下 -

@RestController
@Validated
public class SomeController {
    @Autowired
    private SomeService someService;

    @RequestMapping(value = "/some_list/{id}/some_method", method = RequestMethod.GET)
    public Collection<SomeObject> getCollection(
        @PathVariable @SomeCustomJavaxConstraintValidator String id,
        @RequestParam(required = true) 
            @SomeCustomJavaxConstraintValidator String someOtherID) {

        return someService.getSomething(id, someOtherID);
    }

    // other methods
}

异常看起来像这样(格式化的信息适合问题区域) -

2016-03-13 14:46:09.956 ERROR org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - 
Failed to invoke @ExceptionHandler method: 
    public org.springframework.http.ResponseEntity<SomeEntity> 
        com.hogehoge.GenericExceptionHandler.handleServiceException(
            javax.servlet.http.HttpServletResponse, 
            com.hogehoge.CustomException)
java.lang.NullPointerException: Name is null
    at java.lang.Enum.valueOf(Enum.java:236) ~[na:1.8.0_66]
    at org.springframework.http.HttpMethod.valueOf(HttpMethod.java:27) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.http.server.ServletServerHttpRequest.getMethod(ServletServerHttpRequest.java:87) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:175) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:363) ~[spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:137) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1183) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1020) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [tomcat8-servlet-api-8.0.26.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat8-servlet-api-8.0.26.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [tomcat8-catalina-8.0.26.jar:8.0.26]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1074) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.run(Nio2Endpoint.java:1033) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint.processSocket0(Nio2Endpoint.java:594) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.Nio2Endpoint.processSocket(Nio2Endpoint.java:578) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:86) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:79) [tomcat8-coyote-8.0.26.jar:8.0.26]
    at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) [na:1.8.0_66]
    at sun.nio.ch.Invoker$2.run(Invoker.java:218) [na:1.8.0_66]
    at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) [na:1.8.0_66]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_66]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_66]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat8-util-8.0.26.jar:8.0.26]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_66]

GenericExceptionHandler是一个@ControllerAdvice,就像这样注册 -

@ControllerAdvice
public class GenericExceptionHandler {
    // fields and others......

    @ResponseBody
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<SomeEntity> handleServiceException(
        HttpServletResponse response, CustomException e) {

        // method implementation
    }

我无法在我的本地环境中重现此异常,因为异常显然是随机发生的。我尝试在堆栈跟踪之后调试它,看起来由于某种原因getMethod HttpServletRequest方法返回null(!! ??),结果{{1抛出这个异常,但我不知道为什么会这样。

更新

虽然这是一个Spring Boot应用程序,但它正在一个独立的tomcat服务器上部署。已使用maven插件配置POM文件,以便正确完成重新打包。此外,应用的包装已标记为HttpMethod.valueOf。样本 -

war

2 个答案:

答案 0 :(得分:2)

我检查了最新的Spring源代码HttpEntityMethodProcessor.java(第175行),我发现代码略有变化,现在无法获得NPE。 我看到他们之间来回切换了几次: inputMessage.getMethod()== HttpMethod.GET 和 inputMessage.getMethod()。等于(HttpMethod.GET)

答案 1 :(得分:2)

关于Failed to invoke custom ExceptionHandler的原始问题,可能是因为您的ExceptionHandler仅处理@ExceptionHandler(CustomException.class),而实际引发的例外情况是{ {1}}。我通常也会在我的ExceptionHandler中为NullPointerException添加一个方法(处理程序),这样我就可以处理运行时异常,就像我的自定义异常一样。

关于nullpointer的来源,如上所述,您可以尝试升级Spring启动版本,看看是否能解决问题。