Spring @ExceptionHandler does not work with @ResponseBody

后端 未结 7 1382
南笙
南笙 2020-11-29 23:45

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 se

相关标签:
7条回答
  • 2020-11-30 00:35

    I faced the similar issue, this problem occurs when your Controller method return type and ExceptionHandler return types are not same. Make sure you have exactly same return types.

    Controller method:

    @RequestMapping(value = "/{id}", produces = "application/json", method = RequestMethod.POST)
    public ResponseEntity<?> getUserById(@PathVariable String id) throws NotFoundException {
        String response = userService.getUser(id);
        return new ResponseEntity(response, HttpStatus.OK);
    }
    

    Advice method:

    @ExceptionHandler(NotFoundException.class)
    public ResponseEntity<?> notFoundException(HttpServletRequest request, NotFoundException e) {
        ExceptionResponse response = new ExceptionResponse();
        response.setSuccess(false);
        response.setMessage(e.getMessage());
        return new ResponseEntity(response, HttpStatus.NOT_FOUND);
    }
    

    As you can see return types in both the classes are same ResponseEntity<?>.

    0 讨论(0)
  • 2020-11-30 00:38

    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 ) );
    }
    
    0 讨论(0)
  • 2020-11-30 00:38

    This seems ilke a confirmed Bug (SPR-6902 @ResponseBody does not work with @ExceptionHandler)

    https://jira.springsource.org/browse/SPR-6902

    Fixed in 3.1 M1 though...

    0 讨论(0)
  • 2020-11-30 00:44

    AnnotationMethodHandlerExceptionResolver also need MappingJacksonHttpMessageConverter

    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                    <property name="objectMapper" ref="jacksonObjectMapper" />
                </bean>
            </list>
        </property>
    </bean>
    
    <bean id="jacksonObjectMapper"
        class="iacm.cemetery.framework.web.servlet.rest.JacksonObjectMapper" />
    
    0 讨论(0)
  • 2020-11-30 00:47

    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:

    • String
    • ModelAndView.

    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()));
    }
    
    0 讨论(0)
  • 2020-11-30 00:50

    I am using Spring 3.2.4. My solution to the problem was to make sure that the object I was returning from the exception handler had getters.

    Without getters Jackson was unable to serialize the object to JSON.

    In my code, for the following ExceptionHandler:

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public List<ErrorInfo> exceptionHandler(Exception exception){
        return ((ConversionException) exception).getErrorInfos();
    }
    

    I needed to make sure my ErrorInfo object had getters:

    package com.pelletier.valuelist.exception;
    
    public class ErrorInfo {
    private int code;
    private String field;
    private RuntimeException exception;
    
    public ErrorInfo(){}
    
    public ErrorInfo(int code, String field, RuntimeException exception){
        this.code = code;
        this.field = field;
        this.exception = exception;
    }
    
    public int getCode() {
        return code;
    }
    
    public String getField() {
        return field;
    }
    
    public String getException() {
        return exception.getMessage();
    }
    }
    
    0 讨论(0)
提交回复
热议问题