ControllerAdvice not being invoked but I can still see the exception in the response. Need to handle exceptions centrally

Viewed 715

Since I have just started off with Spring boot, I'm creating a very basic project with very basic rest controllers. The intent is to understand the basics before trying out any complicated code so the examples below are very basic. There is no complex business logic, just minimal lines of code.

I have created a basic project with a simple rest controller, it has the following annotations

@RestController
@RequestMapping("users")
public class UserController
    {

In the get method I have intentionally created a null pointer exception by assigning null to a variable and then checking the length.

@GetMapping(path="/{UserId}",produces = {MediaType.APPLICATION_JSON_VALUE})
        public ResponseEntity<UserViewDTO> getUser(@PathVariable String UserId)
            {

                String firstName = null;
                int len_fname = firstName.length();


                UserViewDTO responseBody= new UserViewDTO();
                responseBody.setFirstname("1stname");
                responseBody.setLastname("lastname");
                responseBody.setEmail("email@gmail.com");
                responseBody.setUserid(UserId);


                return  new ResponseEntity<UserViewDTO>(responseBody,HttpStatus.OK);

            }

As a result of this I get the bellow message in response in Postman.

{
    "timestamp": "2021-03-07T19:56:48.790+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "exception": "java.lang.NullPointerException",
    "message": "No message available",
    "path": "/users/1212121"
}

I wanted to do handle this with @Controller advice from a central class. I created the following

import org.apache.catalina.WebResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class AppExceptionHandler extends ResponseEntityExceptionHandler
    {

        @ExceptionHandler(value= {Exception.class})
        public ResponseEntity<Object> handleAnyException(Exception ex, WebRequest request)
            {
                return  new ResponseEntity<>(
                        ex, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
            }




    }

When I put a debugger the code under the @ControllerAdvice does not even get activated. Also here is my application.properties code

server.error.include-exception=true
server.error.include-message=always
server.error.include-binding-errors=always

What am I doing wrong over here ?

2 Answers

I use it without extending. You should be remove extends ResponseEntityExceptionHandler or you must be override parent class handler method This code is run, You can review the usage here https://github.com/cebrailinanc/spring-cloud/tree/master/product-service/src/main/java/com/cbrl/cloud/product/api

@ControllerAdvice
public class AppExceptionHandler {
    @ExceptionHandler(value = {Exception.class})
    public ResponseEntity<Object> handleAnyException(Exception ex) {
       return new ResponseEntity(ex, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Truth be told i dont see any problem in your @ControllerAdvice .

If possible please remove the value inside the annotation as If there is just one element named value, then the name may be omitted, as in the case of @ExceptionHandler it takes an array of Throwable Class. And also if possible and if not needed please remove WebRequest and use @ResponseBody and @ResponseStatus

@ResponseBody
@ResposneStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
      return e.getMessage();
}
Related