[#26] feat: 불필요한 Exception 제거 및 통합
- CafeMenu, MenuOption, OptionDetail 관련 Exception 통합(BusinessException) - 시스템 관련 에러 핸들러 추가(BasicControllerAdvice) - 불필요한 클래스 제거 - 패키지 이동(account-api security package)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package io.beaniejoy.dongnecafe.common.security
|
||||
package io.beaniejoy.dongnecafe.security
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
@@ -1,4 +1,4 @@
|
||||
package io.beaniejoy.dongnecafe.common.security
|
||||
package io.beaniejoy.dongnecafe.security
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.common.error.advice
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
import io.beaniejoy.dongnecafe.common.response.ApplicationResponse
|
||||
import mu.KLogging
|
||||
@@ -13,11 +14,25 @@ class BasicControllerAdvice {
|
||||
|
||||
companion object : KLogging()
|
||||
|
||||
// 비즈니스 로직 상 에러 처리
|
||||
/**
|
||||
* 예외 상황 (500 시스템 오류 처리)
|
||||
* @param e Exception
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(Exception::class)
|
||||
fun handleException(e: Exception): ApplicationResponse {
|
||||
logger.error { "[COMMON][${e.javaClass.simpleName}] $e" }
|
||||
return ApplicationResponse.fail(errorCode = ErrorCode.COMMON_SERVER_ERROR)
|
||||
}
|
||||
|
||||
/**
|
||||
* 비즈니스 로직 상 에러 처리(예상 가능한 예외 처리)
|
||||
* @param e BusinessException
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ExceptionHandler(BusinessException::class)
|
||||
fun handleBusinessException(e: BusinessException): ApplicationResponse {
|
||||
logger.error { "[${BusinessException::class.simpleName}], <ErrorCode>: ${e.errorCode.name}, <ErrorMessage>: ${e.message}" }
|
||||
logger.error { "[${BusinessException::class.simpleName}] <ErrorCode>: ${e.errorCode.name}, <ErrorMessage>: ${e.message}" }
|
||||
return ApplicationResponse.fail(errorCode = e.errorCode)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package io.beaniejoy.dongnecafe.common.error.constant
|
||||
|
||||
enum class Domain {
|
||||
COMMON,
|
||||
|
||||
AUTH,
|
||||
MEMBER,
|
||||
|
||||
CAFE,
|
||||
CAFE_MENU
|
||||
CAFE_MENU,
|
||||
MENU_OPTION,
|
||||
OPTION_DETAIL
|
||||
}
|
||||
@@ -7,8 +7,10 @@ enum class ErrorCode(
|
||||
val domain: Domain,
|
||||
val subCategory: SubCategory
|
||||
) {
|
||||
// COMMON
|
||||
COMMON_SERVER_ERROR(COMMON, SERVER_ERROR),
|
||||
|
||||
// AUTH(security 관련)
|
||||
AUTH_COMMON_EXCEPTION(AUTH, COMMON),
|
||||
AUTH_MEMBER_NOT_FOUND(AUTH, INVALID_AUTHENTICATE_REQUEST),
|
||||
AUTH_PASSWORD_NOT_VALID(AUTH, INVALID_AUTHENTICATE_REQUEST),
|
||||
AUTH_MEMBER_DEACTIVATED(AUTH, DEACTIVATED),
|
||||
@@ -18,11 +20,16 @@ enum class ErrorCode(
|
||||
|
||||
// CAFE
|
||||
CAFE_NOT_FOUND(CAFE, NOT_FOUND),
|
||||
CAFE_EXISTED(CAFE, EXISTED);
|
||||
CAFE_EXISTED(CAFE, EXISTED),
|
||||
|
||||
companion object {
|
||||
fun convertOrNull(value: String?): ErrorCode? {
|
||||
return values().find { it.name === value }
|
||||
}
|
||||
}
|
||||
// CAFE_MENU
|
||||
CAFE_MENU_NOT_FOUND(CAFE_MENU, NOT_FOUND),
|
||||
|
||||
// MENU_OPTION
|
||||
MENU_OPTION_NOT_FOUND(MENU_OPTION, NOT_FOUND),
|
||||
|
||||
// OPTION_DETAIL
|
||||
OPTION_DETAIL_NOT_FOUND(OPTION_DETAIL, NOT_FOUND)
|
||||
|
||||
;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.beaniejoy.dongnecafe.common.error.constant
|
||||
|
||||
enum class SubCategory {
|
||||
COMMON,
|
||||
SERVER_ERROR,
|
||||
INVALID_AUTHENTICATE_REQUEST,
|
||||
NOT_FOUND,
|
||||
EXISTED,
|
||||
|
||||
@@ -76,6 +76,5 @@ class CafeController(
|
||||
)
|
||||
|
||||
return ApplicationResponse.success("Successfully Cafe[$id] Info Updated")
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.model.response.CafeMenuDetailedInfo
|
||||
import io.beaniejoy.dongnecafe.error.exception.CafeMenuNotFoundException
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.model.request.CafeMenuUpdateRequest
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.model.response.CafeMenuDetailedInfo
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeMenuRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Service
|
||||
@@ -20,14 +21,14 @@ class CafeMenuService(
|
||||
@Transactional(readOnly = true)
|
||||
fun getDetailedInfoByMenuId(menuId: Long, cafeId: Long): CafeMenuDetailedInfo {
|
||||
val cafeMenu = cafeMenuRepository.findByIdOrNull(menuId)
|
||||
?: throw CafeMenuNotFoundException(menuId = menuId, cafeId = cafeId)
|
||||
?: throw BusinessException(ErrorCode.CAFE_MENU_NOT_FOUND)
|
||||
|
||||
return CafeMenuDetailedInfo.of(cafeMenu)
|
||||
}
|
||||
|
||||
fun updateInfoAndBulkUpdate(menuId: Long, cafeId: Long, resource: CafeMenuUpdateRequest) {
|
||||
val cafeMenu = cafeMenuRepository.findByIdOrNull(menuId)
|
||||
?: throw CafeMenuNotFoundException(menuId = menuId, cafeId = cafeId)
|
||||
?: throw BusinessException(ErrorCode.CAFE_MENU_NOT_FOUND)
|
||||
|
||||
cafeMenu.updateInfo(name = resource.name!!, price = resource.price)
|
||||
|
||||
@@ -36,7 +37,7 @@ class CafeMenuService(
|
||||
|
||||
fun deleteByCafeMenuId(menuId: Long, cafeId: Long) {
|
||||
val cafeMenu = cafeMenuRepository.findByIdOrNull(menuId)
|
||||
?: throw CafeMenuNotFoundException(menuId = menuId, cafeId = cafeId)
|
||||
?: throw BusinessException(ErrorCode.CAFE_MENU_NOT_FOUND)
|
||||
|
||||
cafeMenuRepository.delete(cafeMenu)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.error.exception.MenuOptionNotFoundException
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.model.request.MenuOptionUpdateRequest
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.MenuOptionRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
@@ -16,7 +17,7 @@ class MenuOptionService(
|
||||
fun bulkUpdate(resources: List<MenuOptionUpdateRequest>) {
|
||||
resources.forEach {
|
||||
val menuOption = menuOptionRepository.findByIdOrNull(it.menuOptionId)
|
||||
?: throw MenuOptionNotFoundException(it.menuOptionId)
|
||||
?: throw BusinessException(ErrorCode.MENU_OPTION_NOT_FOUND)
|
||||
|
||||
if (it.isDelete) {
|
||||
menuOptionRepository.delete(menuOption)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.error.exception.OptionDetailNotFoundException
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.model.request.OptionDetailUpdateRequest
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.OptionDetailRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
@@ -15,7 +16,7 @@ class OptionDetailService(
|
||||
fun bulkUpdate(resources: List<OptionDetailUpdateRequest>) {
|
||||
resources.forEach {
|
||||
val optionDetail = optionDetailRepository.findByIdOrNull(it.optionDetailId)
|
||||
?: throw OptionDetailNotFoundException(it.optionDetailId)
|
||||
?: throw BusinessException(ErrorCode.OPTION_DETAIL_NOT_FOUND)
|
||||
|
||||
if (it.isDelete) {
|
||||
optionDetailRepository.delete(optionDetail)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.error.exception
|
||||
|
||||
class CafeMenuNotFoundException(menuId: Long, cafeId: Long) :
|
||||
RuntimeException("Cafe[${cafeId}]의 Menu[${menuId}]는 존재하지 않는 메뉴입니다.")
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.error.exception
|
||||
|
||||
class MenuOptionNotFoundException(menuOptionId: Long) : RuntimeException("MenuOption[$menuOptionId] is not found")
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.error.exception
|
||||
|
||||
class OptionDetailNotFoundException(optionDetailId: Long) : RuntimeException("OptionDetail[$optionDetailId] is not found")
|
||||
@@ -1,7 +1,8 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
|
||||
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.entity.CafeMenu
|
||||
import io.beaniejoy.dongnecafe.error.exception.CafeMenuNotFoundException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeMenuRepository
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.MenuOptionRepository
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.OptionDetailRepository
|
||||
@@ -81,12 +82,12 @@ internal class CafeMenuServiceTest {
|
||||
`when`(mockCafeMenuRepository.findById(findCafeMenuId)).thenReturn(Optional.empty())
|
||||
|
||||
// then
|
||||
val exception = assertThrows<CafeMenuNotFoundException> {
|
||||
val exception = assertThrows<BusinessException> {
|
||||
// when
|
||||
mockCafeMenuService.getDetailedInfoByMenuId(findCafeMenuId, findCafeId)
|
||||
}
|
||||
|
||||
assertEquals("Cafe[${findCafeId}]의 Menu[${findCafeMenuId}]는 존재하지 않는 메뉴입니다.", exception.message)
|
||||
assertEquals(ErrorCode.CAFE_MENU_NOT_FOUND, exception.errorCode)
|
||||
|
||||
verify(mockCafeMenuRepository).findById(findCafeMenuId)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user