I try to configure a spring exception handler for a rest controller that is able to render a map to both xml and json based on the incoming accept header. It throws a 500 servlet exception right now.
This works, it picks up the home.jsp:
@ExceptionHandler(IllegalArgumentException.class) public String handleException(final Exception e, final HttpServletRequest request, Writer writer) { return "home"; }
This does not work:
@ExceptionHandler(IllegalArgumentException.class) public @ResponseBody Map<String, Object> handleException(final Exception e, final HttpServletRequest request, Writer writer) { final Map<String, Object> map = new HashMap<String, Object>(); map.put("errorCode", 1234); map.put("errorMessage", "Some error message"); return map; }
In the same controller mapping the response to xml or json via the respective converter works:
@RequestMapping(method = RequestMethod.GET, value = "/book/{id}", headers = "Accept=application/json,application/xml") public @ResponseBody Book getBook(@PathVariable final String id) { logger.warn("id=" + id); return new Book("12345", new Date(), "Sven Haiges"); }
You can define the @ExceptionHandler method to handle the exceptions as shown. This method should be used for writing the Controller Advice class file. Now, use the code given below to throw the exception from the API. The complete code to handle the exception is given below.
The exception handler method takes in an exception or a list of exceptions as an argument that we want to handle in the defined method. We annotate the method with @ExceptionHandler and @ResponseStatus to define the exception we want to handle and the status code we want to return.
Exception Handling in Spring Boot helps to deal with errors and exceptions present in APIs so as to deliver a robust enterprise application. This article covers various ways in which exceptions can be handled in a Spring Boot Project. Let's do the initial setup to explore each approach in more depth.
Your method
@ExceptionHandler(IllegalArgumentException.class) public @ResponseBody Map<String, Object> handleException(final Exception e, final HttpServletRequest request, Writer writer)
does not work because it has the wrong return type. @ExceptionHandler methods have only two valid return types:
See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html for more information. Here's the specific text from the link:
The return type can be a String, which is interpreted as a view name or a ModelAndView object.
In response to the comment
Thanx, seems I overread this. That's bad... any ideas how to provides exceptions automatically in xml/json format? – Sven Haiges 7 hours ago
Here's what I've done (I've actually done it in Scala so I'm not sure if the syntax is exactly correct, but you should get the gist).
@ExceptionHandler(Throwable.class) @ResponseBody public void handleException(final Exception e, final HttpServletRequest request, Writer writer) { writer.write(String.format( "{\"error\":{\"java.class\":\"%s\", \"message\":\"%s\"}}", e.getClass(), e.getMessage())); }
Thanx, seems I overread this. That's bad... any ideas how to provides exceptions automatically in xml/json format?
New in Spring 3.0 MappingJacksonJsonView can be utilized to achieve that:
private MappingJacksonJsonView jsonView = new MappingJacksonJsonView(); @ExceptionHandler(Exception.class) public ModelAndView handleAnyException( Exception ex ) { return new ModelAndView( jsonView, "error", new ErrorMessage( ex ) ); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With