简体   繁体   中英

how to catch connection refused exception of spring boot data jpa

I'm creating microservice application with spring boot. so, just think there are 2 services called A and B. A makes a request to do some execution to B by HTTP. so, the database might not be available in some times when the request are coming. that kind of situation, A service has to know if it's a connection error from the database side or one of other exceptions from the service B. if A server will be known about that, A server can replay the request again after connection fixed. for that I want to filter the connection-exception from the exception that MYSQL throws. but I tried to catch it in the service layer by using Exception . unfortunately the error is not caught. the code like below.

try {
   userRepository.incrementReputationByOne(userUid);
} catch (Exception e) {
   //the exception doesn't come here
   e.printStackTrace();
}

I want to set the Http status code as HttpStatus.SERVICE_UNAVAILABLE . then the service A know that the error is due to the connection issue oof the database or endpoint. the the server can retry the request again after while or some scheduled time.

You can't catch the SQLException related to the repository in the service layer like this. because the transaction is managed from the service layer. therefore you have to use the try-catch block in the controller layer. otherwise, the request status will be internal-server-error . if you catch the transaction error in the controller layer, you have to duplicate the same catch process for each. therefore you can use a ControllerAdvice . anyway, the spring does not throw the SQL exception directly. instead of that spring will throw the CannotCreateTransactionException . it contains the ConnectException . spring provides a handy method to find out if it contains the exception that you are looking for.


without ControllerAdvice

in the controller's method, you can catch the error like below.

    @PutMapping
    public ResponseEntity<?> incrementByOne(@RequestParam("user_uid") String userUid) {
        try {
            userService.incrementReputationByOne(userUid);
        } catch (CannotCreateTransactionException e) {
            if (e.contains(ConnectException.class)) {
                log.debug("ConnectException {}", e.getMessage());
                return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
            } else {
                ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        }
        return ResponseEntity.ok().build();
    }

with ControllerAdvice

if you use ControllerAdvice to catch the exception, it is very easy and you don't want to cath the database exception the service layer or controller layer as well.

@ControllerAdvice
@Slf4j
@ResponseBody
public class DatabaseExceptionHandler {
    @ExceptionHandler(value = {CannotCreateTransactionException.class})
    public ResponseEntity<?> cannotCreateTransactionException(CannotCreateTransactionException exception, WebRequest request) {
        if (exception.contains(ConnectException.class)) {
            log.error("DB ConnectException :  {}", exception.getMessage());
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
        }else {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}

in your service layer keep your code without catching errors. the ControllerAdvice will take care of the exceptions.

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