Home > Software design >  Java Spring Boot: Exception Handling
Java Spring Boot: Exception Handling

Time:11-23

A little new to the Java Spring Boot flavor of webservices -- so please be gentle. Why do most Spring Boot Controller examples not show any exceptions being captured? I see some of my fellow developers do this a lot. And the answer is: it's a common convention. But why. Am I missing a key concept of web services created using Spring Boot?

For example:

@PostMapping(path = "/sampleEndpoint/v1/myEndpoint", produces = "application/json")
public ResponseEntity<String> myEndpoint(@RequestBody MyEndpointRequest myEndpointRequest) {
    
     MyEndpointResponse response = someService.myEndpoint(myEndpointRequest);
     return new ResponseEntity<>(response, HttpStatus.OK);
}

I would think, with respects to the architecture you would add AT LEAST a try/catch block with say some logging, and throw a new exception with the exceptions message:

@PostMapping(path = "/sampleEndpoint/v1/myEndpoint", produces = "application/json")
public ResponseEntity<String> myEndpoint(@RequestBody MyEndpointRequest myEndpointRequest) {


  try{  
       MyEndpointResponse response = someService.myEndpoint(myEndpointRequest);
       return new ResponseEntity<>(response, HttpStatus.OK);

  }catch(Exception ex){
    //Your favorite logger:
    log.error("STACK_TRACE: {}", StaticClass.stackTraceToString(ex));

    //throw exception for calling or consuming system/application:
    throw new MiscException(ex.getMessage());
  }
}

A couple of things to give context to this question (observation):

  • Use multiple data sources: a couple of databases, and some other web services (gives our client a one stop place to get their data.
  • Using this webservice with potentially 4 different client side /presentation layer type of applications.
  • My team would like to capture unexpected exceptions emanating from the data sources we tap into...and log them.

CodePudding user response:

Well it's up to developer to implement catch of exceptions mechanism. But it's a good practise to define exceptions types and error codes/messages for that. Let's say you have an endpoint which fetch product with id, but there is no product with that id, in that case client will receive http 500 code with internal server error message. This will confuse users and also developers, what was the real cause of that error.

So prevent those, you can get help from @ControllerAdvice annotation, which will allow to apply exception handlers to more than one or all controllers. First you will define your custom exceptions like :

public class ProductNotFoundException extends RuntimeException {

    public ProductNotFoundException(Long id) {

        super(String.format("Product with id %d not found", id));
    }
}

and then you can define your ControllerAdvice class:

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {

 @ExceptionHandler(ProductNotFound.class)
    public ResponseEntity<Object> handleProductNotFoundException(
        ProductNotFoundException ex, WebRequest request) {

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("message", "Product not found");

        return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
    }
}
  • Related