14

I have a Spring MVC controller with some simple REST service requests. I would like to add some error handling when specific exceptions are thrown from my services, but I cannot get a handler method annotated with @ExceptionHandler to actually ever be called. Here is one service I am deliberately throwing an exception to try and get my handler method to take over. The handler method is never invoked and Spring just returns a 500 error to the calling client. Do you have any ideas on what I'm doing wrong?

@ExceptionHandler(IOException.class) public ModelAndView handleIOException(IOException ex, HttpServletRequest request, HttpServletResponse response) { response.sendError(HttpServletResponse.SC_FORBIDDEN); System.out.println("It worked!"); return new ModelAndView(); } @RequestMapping(value = "/json/remove-service/{id}", method = RequestMethod.DELETE) public void remove(@PathVariable("id") Long id) throws IOException { throw new IOException("The handler should take over from here!"); } 
0

4 Answers 4

14

Frustratingly, I have suffered from this as well. I discovered that if you mistakenly implement Throwable instead of Exception the Exception resolver will just rethrow your Throwable as a IllegalStateException. This will fail to invoke your @ExceptionHandler.

If you've implemented Throwable instead of Exception try changing it to Exception instead.

Here's the code in question from InvocableHandlerMethod

catch (InvocationTargetException e) { // Unwrap for HandlerExceptionResolvers ... Throwable targetException = e.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else if (targetException instanceof Error) { throw (Error) targetException; } else if (targetException instanceof Exception) { throw (Exception) targetException; } else { String msg = getInvocationErrorMessage("Failed to invoke controller method", args); throw new IllegalStateException(msg, targetException); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

such a common mistake, I did this today, In my case Intellij culprit for this, which extends Throwable by default.
13

This tip on the Spring forum may help you.

Likely you have configured the beans for your DispatchServlet in a webmvc-servlet.xml file (the *-servlet.xml file may be named differently)

If the XML file already includes another ExceptionResolver (like SimpleMappingExceptionResovler Spring wont automatically add any other resolvers for you. So manually adding the annotation resolver like so:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver" /> 

Should enable the @HandlerException processing.

3 Comments

AnnotationMethodHandlerExceptionResolver is now deprecated so this doesn't help in newer versions of Spring.
Using this bean with the p:order property set to the highest priority (1) managed to fix my problem.
@MattFriedman Just replacing AnnotationMethodHandlerExceptionResolver with org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver worked for me
4

I have found that @ExceptionHandler works with Throwable when you define method in such a manner:

@ExceptionHandler(Throwable.class) @ResponseBody public String handleException(Throwable e) { } 

In this case method has only one argument of type Throwable. If I try to use in this method some additional parameters (I tried to use Model), I receive 500 exception (this method isn't call). However this still works when additional parameters are HttpServlerRequest or HttpServlerResponse.

Comments

0

It will not work, because when you return String you return View name.

Now your Spring MVC controller is searching for This method is never called! Why not?! view and can find.

Make sure that @ExceptionHandler is mapped to existing view.

2 Comments

That would most likely result in a 404, not a 500.
Sorry, the point is that the method is never called, so what is returned is irrelevant. I changed what is being returned.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.