简体   繁体   中英

@ControllerAdvice Spring - Return type as a custom object and not ModelAndView

I've been tasked to expose the exceptions thrown from the @RequestMapping methods in controllers to the UI as JSON objects. While googling, I found out about ControllerAdvice and I guess I need something similar to that. The only problem that I see in all the examples is the return type - they are returning ModelAndView whereas I need to return a custom object as return type. Here is my sample code:

Controller class:

@RequestMapping(value="/abc", method=RequestMethod.GET)
@ResponseBody
public MyModel getResponse(@RequestParam String id, 
                            HttpServletRequest request) throws SQLException 
   {
    boolean exceptionFlag = true;  
         if (exceptionFlag){  
        throw new SQLException();  
    } 
     return myModel;
  }

ExceptionHandlerClass:

@ControllerAdvice
public class ExceptionHandler {
        @ExceptionHandler(SQLException.class)  
        public MyCustomException handleSQLException(SQLException exception)
        {
            MyCustomException ex = new MyCustomException();
            ex.setExceptionCode("MyCode");
            ex.setExceptionDescription(exception.getMessage());     
            return ex;
        }

It complains that it couldn't find the JSP (WARN:org.apache.jasper.servlet.JspServlet:PWC6117: File "rest\\support\\abc.jsp" not foundnull)

You probably want to wrap your exception inside of a ResponseEntity<T> , so that you can also return an HttpStatus code along with the json body.

@ControllerAdvice
@RequestMapping(produces = "application/json")
@ResponseBody
public class RestControllerAdvice {


    @ExceptionHandler(EntityNotFoundException .class)
    public ResponseEntity<Map<String,Object>> notFoundException(final EntityNotFoundException e) {

        Map<String,Object> errorInfo = new HashMap<>();
        errorInfo.put("error message",e.getMessage());
        errorInfo.put("timestamp", new Date());
        return new ResponseEntity<Map<String,Object>>(errorInfo, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(QueryParameterNotSupportedException.class)
    public ResponseEntity<Map<String,Object>> unrecognizedParameter(final QueryParameterNotSupportedException e) {

        Map<String,Object> errorInfo = new LinkedHashMap<>();
        errorInfo.put("timestamp", new Date());
        errorInfo.put("errorMessage",e.getMessage());
        errorInfo.put("allowableParameters",e.getValidArgs());

        return new ResponseEntity<Map<String,Object>>(errorInfo, HttpStatus.BAD_REQUEST);

    }

In the example above the type "T" is a Map<String,Object> , but it can be any type that is serializable by Jackson. Also, notice there is a class level @ResponseBody annotation present, which instructs spring to convert the return methods of every method in the class to json before returning.

The ExceptionHandler well catch the SQLException ? If it does, maybe this will do the tricks :

@ControllerAdvice
public class ExceptionHandler {

    @ResponseBody
    @ExceptionHandler(SQLException.class)  
    public MyCustomException handleSQLException(SQLException exception) {
        MyCustomException ex = new MyCustomException();
        ex.setExceptionCode("MyCode");
        ex.setExceptionDescription(exception.getMessage());     
        return ex;
    }

}

If you use the @ResponseBody annotation on a controller action method, you can return any type. You will need Jackson2 on your classpath.

You have to modify the exception handler method like @Basemasta says:

@ControllerAdvice
public class ExceptionHandler {

    @ResponseBody
    @ExceptionHandler(SQLException.class)  
    public MyCustomException handleSQLException(SQLException exception) {
        MyCustomException ex = new MyCustomException();
        ex.setExceptionCode("MyCode");
        ex.setExceptionDescription(exception.getMessage());     
        return ex;
    }
}

And include Jackson mapper in your application-Context.xml... This configuration worked for me:

<bean id="jacksonMessageChanger" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">         <property name="supportedMediaTypes" value="application/json"/>
 </bean>
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
 <property name="messageConverters">
     <util:list id="beanList">
     <ref bean="jacksonMessageChanger"/>
     </util:list>
 </property>
</bean>

Here you have a tutorial for returning JSON from Spring: http://www.journaldev.com/2552/spring-restful-web-service-example-with-json-jackson-and-client-program

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM