@ExceptionHandler doesn't catch HttpMessageNotReadableException
Asked Answered
U

4

14

I have the following exception handler:

@ControllerAdvice
public class MyExceptionHandler {
  private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandler.class);
    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handle(HttpMessageNotReadableException e) {
        logger.warn("HttpMessageNotReadableException occurred.", e);
        throw e;
    }

But it doesn't catch HttpMessageNotReadableException?! In my logs I see (it prints spring itself):

2017-07-04 13:26:38,699 DEBUG org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.getMethodArgumentValues:164 - Failed to resolve argument 0 of type 'com.finvale.model.Client'
org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not deserialize value of type java.time.LocalDate from String "Invalid date": Text 'Invalid date' could not be parsed at index 0
 at [Source: java.io.PushbackInputStream@4f30395; line: 1, column: 103] (through reference chain: com.finvale.model.Client["birthDay"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.time.LocalDate from String "Invalid date": Text 'Invalid date' could not be parsed at index 0
 at [Source: java.io.PushbackInputStream@4f30395; line: 1, column: 103] (through reference chain: com.finvale.model.Client["birthDay"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:240)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:225)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:201)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:128)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:108)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

Is it possible to catch this exception in my ExceptionHandler ?

P.S.

I agree that my code contains mistake. I neeed to specify type in annotation. I changed it like this:

 @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handle(HttpMessageNotReadableException e) {

but I still see same behaviour.

handle method doesn't invoke

Unending answered 4/7, 2017 at 10:32 Comment(4)
maybe you should not "re-throw" it!? (throw e;)Egor
@Egor this code doesn;t invokeUnending
...thanks for updates, now I would ask whether MyExceptionHandler is correctly (spring) configured/scanned? (Can you verify in logging the initialization of ControllerAdvice)Egor
Please post solutions as answers not as updates to your question. This is for future visitors and to avoid confusion. Thank you.Bungle
U
3

Finally I found solution:

Root cause was that there was 2 places with @ExceptionHandler

  • Inside controller
  • Inside the Separated class MyExceptionHandler described in question.

I moved method to MyExceptionHandler ans it became working.

Unending answered 4/7, 2017 at 13:51 Comment(1)
i only have 1 doesnt workCyd
W
10

You have to specify the class that the handler needs to handle. Like:

@ExceptionHandler(HttpMessageNotReadableException.class)

See here for further reading for example. Or there for a "complete" discussion regarding spring and exception handling.

Womanly answered 4/7, 2017 at 10:40 Comment(4)
I changed code base accordingyour advice, but behaviour was not changedUnending
Doesnt work. wont catch itCyd
@PhilipRego "Doesnt work" isnt a very helpful problem description. When you think you have a similar problem, but the solutions given here aren't working, then consider to write up a completely new question. Include a link to this question here, and a good minimal reproducible example . But see ... your comment here, how does it help anyone? It worked for me back then, and 10 people upvoted the answer, so others found it helpful, too. That is all I can say about it ...Womanly
Let's people know answer need to be update it then to the full answer. You need a method with the correct params. You just posted @ExceptionHandler(HttpMessageNotReadableException.class). Also think the location of the method probably makes a difference.Cyd
U
3

Finally I found solution:

Root cause was that there was 2 places with @ExceptionHandler

  • Inside controller
  • Inside the Separated class MyExceptionHandler described in question.

I moved method to MyExceptionHandler ans it became working.

Unending answered 4/7, 2017 at 13:51 Comment(1)
i only have 1 doesnt workCyd
S
1

Change @ExceptionHandler to @ExceptionHandler(value = HttpMessageNotReadableException.class)

And instead of re-throwing same exception, its better to return a custom object containing that error message in meaningful way

Shulins answered 4/7, 2017 at 10:37 Comment(1)
already tried didnt workCyd
L
0

Mine worked after I imported the class.In the beginning it was not recognizing the class. But it worked after importing import org.springframework.http.converter.*;

Linchpin answered 16/6, 2022 at 0:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.