diff --git a/src/main/java/com/f_lab/la_planete/controller/GlobalExceptionHandler.java b/src/main/java/com/f_lab/la_planete/controller/GlobalExceptionHandler.java new file mode 100644 index 00000000..3455534b --- /dev/null +++ b/src/main/java/com/f_lab/la_planete/controller/GlobalExceptionHandler.java @@ -0,0 +1,68 @@ +package com.f_lab.la_planete.controller; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.Hidden; +import jakarta.persistence.PessimisticLockException; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.exception.LockTimeoutException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.transaction.TransactionSystemException; +import org.springframework.web.ErrorResponse; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@Hidden +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(IllegalStateException.class) + public ResponseEntity handleIllegalStateException(IllegalStateException e) { + return ResponseEntity + .status(HttpStatus.CONFLICT) + .body(ErrorResponse.of(e.getMessage(), HttpStatus.CONFLICT.value())); + } + + /** + * 데이터베이스 관련 예외 (e.g. 주로 락을 얻는 대기시간이 오래되어서 요청을 반환할 때) + */ + @ExceptionHandler(JpaSystemException.class) + public ResponseEntity handleJpaSystemException(JpaSystemException e) { + log.error("JpaSystemException occurred", e); + return ResponseEntity + .status(HttpStatus.SERVICE_UNAVAILABLE) + .body(ErrorResponse.of( + "현재 너무 많은 요청을 처리하고 있습니다. 다시 시도해주세요", + HttpStatus.SERVICE_UNAVAILABLE.value())); + } + + /** + * 어플리케이션에서 처리하지 못한 다른 모든 예외 + */ + @ExceptionHandler(Exception.class) + public ResponseEntity handleGenericException(Exception e) { + log.error("Unexpected Error occurred. Requires Potential Handling", e); + return ResponseEntity + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(ErrorResponse.of( + "알 수 없는 오류가 발생했습니다. 다시 시도해주세요", + HttpStatus.INTERNAL_SERVER_ERROR.value())); + } + + @Getter + @AllArgsConstructor + static class ErrorResponse { + private String message; + + @JsonProperty("status_code") + private int statusCode; + + public static ErrorResponse of(String message, int statusCode) { + return new ErrorResponse(message, statusCode); + } + } +} diff --git a/src/main/java/com/f_lab/la_planete/service/OrderService.java b/src/main/java/com/f_lab/la_planete/service/OrderService.java index 14eb821d..d5d43e40 100644 --- a/src/main/java/com/f_lab/la_planete/service/OrderService.java +++ b/src/main/java/com/f_lab/la_planete/service/OrderService.java @@ -52,12 +52,7 @@ public OrderCreateResponseDTO createFoodOrder(OrderCreateRequestDTO request) { } private Food findFoodWithLock(Long foodId) { - try { - return foodRepository.findFoodByFoodIdWithPessimisticLock(foodId); - } catch(PessimisticLockException | PessimisticLockingFailureException e) { - log.warn("Pessimistic lock failure on food ID: {}", foodId, e); - throw new IllegalStateException("오류 다시 시도해 주시길 바랍니다."); - } + return foodRepository.findFoodByFoodIdWithPessimisticLock(foodId); } }