2012-03-28 16 views
14

Mam kontroler Spring MVC z kilkoma prostymi żądaniami usługi REST. Chciałbym dodać trochę obsługi błędów, gdy wyjątki są wyrzucane z moich usług, ale nie mogę uzyskać metody obsługi opisanej za pomocą @ExceptionHandler, aby rzeczywiście zostać wywołanym. Oto jedna z usług celowo rzucając wyjątek, aby spróbować przejąć kontrolę nad moją metodą obsługi. Metoda obsługi nigdy nie jest wywoływana, a Spring po prostu zwraca błąd 500 do klienta wywołującego. Czy masz jakieś pomysły na temat tego, co robię źle?Metoda Spring MVC @ ExceptionHandler w kontrolerze nigdy nie jest wywoływana

@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!"); 
} 

Odpowiedz

13

Ten tip on the Spring forum może ci pomóc.

Prawdopodobny skonfigurowaniu fasolę do DispatchServlet w pliku webmvc-servlet.xml (The * -servlet.xml plik może być nazwane inaczej)

Jeśli plik XML zawiera już inny ExceptionResolver (jak SimpleMappingExceptionResovler Wiosna przyzwyczajenie automatycznie dodawać innych resolwera dla ciebie to ręcznie dodając resolverowi adnotacji tak:..

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

powinien umożliwiać przetwarzanie @HandlerException

+3

'AnnotationMethodHandlerExceptionResolver' jest teraz przestarzałe, więc to nie pomaga w nowszych wersjach Spring. –

+0

Użycie tego komponentu z właściwością 'p: order' ustawioną na najwyższy priorytet (1) rozwiązało mój problem. – Alex

+0

@MattFriedman Właśnie zastępuje 'AnnotationMethodHandlerExceptionResolver' z' org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver' pracował dla mnie –

0

To nie zadziała, ponieważ po zwrocie String zwrócisz Wyświetl nazwę.

Teraz twój kontroler Spring MVC szuka tej metody nigdy nie jest wywoływana! Dlaczego nie?! zobacz i znajdź.

Upewnij się, że @ExceptionHandler jest zmapowany do istniejącego widoku.

+0

To najprawdopodobniej spowoduje 404, a nie 500. – skaffman

+1

Niestety, chodzi o to, że metoda nigdy nie jest wywoływana, więc to, co jest zwracane, jest nieistotne. Zmieniłem to, co jest zwracane. – 11101101b

12

Frustrująco, cierpiałem również z tego powodu. Odkryłem, że jeśli omyłkowo zaimplementujesz Throwable zamiast Exception, to wyjątek zostanie ponownie zgłoszony przez użytkownika Throwable jako IllegalStateException. Nie powiodą się one wywoływać twojego @ExceptionHandler.

Jeśli zaimplementowano Throwable zamiast Exception, spróbuj zamiast tego zmienić na Exception.

Oto kod w pytaniu od 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); 
      } 
     } 
4

I odkryli, że @ExceptionHandler współpracuje z Throwable podczas definiowania metody w taki sposób:

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

} 

W metodzie tej sprawy ma tylko jeden argument typu Throwable. Jeśli spróbuję użyć w tej metodzie pewnych dodatkowych parametrów (próbowałem użyć Modelu), otrzymam 500 wyjątków (ta metoda nie jest wywołana). Jednak nadal działa, gdy dodatkowe parametry to HttpServlerRequest lub HttpServlerResponse.

Powiązane problemy