Spring Boot Exception Handling

By | | Updated : 2021-05-05 | Viewed : 422 times

Spring Boot Exception Handling

We will learn here how to develop the exception handling for the spring boot application. Here Spring provided different ways for adding the exceptions to handle the smooth execution.

@Exceptionhandler In Controller

We can use @ExceptionHandler in Controller to show the exception messages. Please see the code snippet below given.

@Exceptionhandler In Controller
@Controller
@RequestMapping(path = "/api/org")
public class EmployeeController {

    @GetMapping(path = "/employee")
    public ResponseEntity<Employee> getEmployee(@Valid @RequestBody Employee employee) throws Exception {
        if(employee.getId() != 1001) {
            throw new EmployeeNotFoundException(employee.getId());
        }
        return new ResponseEntity(employee, HttpStatus.OK);
    }
    @ExceptionHandler
    @ResponseBody
    public String handleException (EmployeeNotFoundException e) {
        return "Exception :" + e.toString();
    }
}

So here we have thrown the exception for showing the error message to the client. In @ExceptionHandler we returned the error message as JSON.

Implementing the @ExceptionHandler is not good practice. So we need to think of other options like an external class which will be common for other exceptions.

Using @ResponseStatus

ProductController.java
@Controller
@RequestMapping(path = "/api/order")
public class ProductController {

    @GetMapping(path = "/product")
    public ResponseEntity<Product> getEmployee(@Valid @RequestBody Product product) throws Exception {
        if(product.getId() != 1001) {
            throw new ProductNotFoundException(product.getId());
        }
        return new ResponseEntity(product, HttpStatus.OK);
    }
}
ProductNotFoundException.java
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Product does not existed")
public class ProductNotFoundException extends RuntimeException {

    public ProductNotFoundException(int id) {
        super();
    }
}

Notice above given snippets the ProductNotFoundException thrown with the message "Product does not exist."

In the case of @ResponseStatus, if we want to create the message dynamically it would be a bit critical and have less maintenance.

Global Exception Handler

RestAPIController.java
@RestController
@RequestMapping(path = "/api/rest/org")
public class RestAPIController {

    @Autowired
    EmployeeService employeeService;

    @GetMapping(path = "/employee2")
    public ResponseEntity<Employee> getEmployee1(@Valid @RequestBody Employee employee) {

        if(employee.getId() != 1001) {
             employeeService.getEmployee1(employee);
        }
        return new ResponseEntity(employee, HttpStatus.OK);
    }

}
RestExceptionHandler.java
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        String error = "Malformed JSON request";
        return buildResponseEntity(new Error(HttpStatus.BAD_REQUEST, error, ex));
    }


    @ExceptionHandler(value = {  MyResourceNotFoundException.class })
    protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) {
        final String bodyOfResponse = "This should be application specific";
        String error = "Product not found.";
        return buildResponseEntity(new Error(HttpStatus.NOT_FOUND,error,ex) );

    }
    private ResponseEntity<Object> buildResponseEntity(Error error) {
        return new ResponseEntity<>(error, error.getStatus());
    }
}

Here we can write ExceptionHandlers with the customized message as many as we want. It is centralized ExceptionHandlers and will be very easy to maintain.

If you need the entire codebase for this example you can refer to the GitHub repo SpringBoot-Exception-Handler-Example-App

Leave A Reply