Catching a ArithmeticException in RestController in SpringBoot 2.0.4.RELEASE

Viewed 476

I have a basic SpringBoot 2.0.4.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.

I've created this class to manage the Exceptions:

@ControllerAdvice
@RestControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    public RestResponseEntityExceptionHandler() {
        super();
    }


    // 500

    @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

the method Handles the RuntimeException and ArithmeticException extends RuntimeException.

To test it I've created this method ;

GetMapping(path = "/getUsers", consumes = "application/json", produces = "application/json")
public ResponseEntity<List<User>> testErrors(HttpServletRequest request) {

    double ss = 3 /0;

    return ResponseEntity.ok(userService.findAll());

}

expecting that will only returns a HttpStatus.INTERNAL_SERVER_ERROR but instead it returns"

{"timestamp":"2018-08-31T09:21:21.717+0000","status":500,"error":"Internal Server Error","message":"/ by zero","trace":"java.lang.ArithmeticException: / by zero\n\tat ...

With this method

 @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }

I have the full trace: {"timestamp":"2018-09-03T07:04:58.803+0000","status":500,"error":"Internal Server Error","message":"/ by zero","trace":"java.lang.ArithmeticException: / by zero\n\tat

and with this one, I don't see anything in the console with curl:

 @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public void handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);

    }

and this other one, also nothing in the console:

@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class })
    /*500*/
    public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);


        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

    }
3 Answers

Perhaps piradian didn't point it out specifically, but the problem seems to be the return type of your handleInternal method. In the code, which you have provided, the return type is BodyBuilder and you return the value returned by ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR). Actually, as the BodyBuilder name suggests, it represents an implementation of Builder pattern. What you should actually do in this case is this:

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

And change the return type of the method to ResponseEntity or ResponseEntity<Object> (the body is empty in your case, so there really is no big difference).

However, taking into account that there is no body returned in your example and you already have your method annotated with @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR), all you could do is change the return type to void and not return anything - this is exactly what piradian suggested. This should work as well.

Try this:

@ExceptionHandler({NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class, RuntimeException.class})
/* 500 */
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public void handleInternal(final RuntimeException ex, final WebRequest request) {
    logger.error("500 Status Code", ex);

}

use this one

@RestControllerAdvice//insted of @ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {    
   @ExceptionHandler(value = { Exception.class, RuntimeException.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public BodyBuilder handleInternal(final RuntimeException ex, final WebRequest request) {
        logger.error("500 Status Code", ex);

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
Related