-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BSVR-63] custom exception & global exception handler 추가 #15
Changes from all commits
84b9c28
198af3c
77807ad
e1a439d
3e1c6fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.depromeet.spot.application.common.exception; | ||
|
||
import org.depromeet.spot.common.exception.BusinessException; | ||
|
||
public record ErrorResponse(String code, String message) { | ||
|
||
public static ErrorResponse from(BusinessException e) { | ||
return new ErrorResponse(e.getCode(), e.getMessage()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package org.depromeet.spot.application.common.exception; | ||
|
||
import org.depromeet.spot.common.exception.BusinessException; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
@RestControllerAdvice | ||
public class SpotAppExceptionHandler { | ||
|
||
private static final String EXCEPTION_LOG_TEMPLATE = "code = {}, message = {}"; | ||
|
||
@ExceptionHandler(BusinessException.class) | ||
protected ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) { | ||
var code = e.getCode(); | ||
var message = e.getMessage(); | ||
var httpStatus = e.getHttpStatus(); | ||
|
||
log.error(EXCEPTION_LOG_TEMPLATE, code, message); | ||
var response = ErrorResponse.from(e); | ||
|
||
return ResponseEntity.status(httpStatus).body(response); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
.gradle | ||
build/ | ||
!gradle/wrapper/gradle-wrapper.jar | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
### IntelliJ IDEA ### | ||
.idea/modules.xml | ||
.idea/jarRepositories.xml | ||
.idea/compiler.xml | ||
.idea/libraries/ | ||
*.iws | ||
*.iml | ||
*.ipr | ||
out/ | ||
!**/src/main/**/out/ | ||
!**/src/test/**/out/ | ||
|
||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
bin/ | ||
!**/src/main/**/bin/ | ||
!**/src/test/**/bin/ | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
|
||
### VS Code ### | ||
.vscode/ | ||
|
||
### Mac OS ### | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
dependencies { | ||
implementation("org.springframework.boot:spring-boot-starter-web") | ||
} | ||
|
||
tasks.jar { enabled = true } | ||
tasks.bootJar { enabled = false } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.depromeet.spot.common.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class BusinessException extends RuntimeException { | ||
|
||
private final HttpStatus httpStatus; | ||
private final String code; | ||
|
||
public BusinessException(ErrorCode errorCode) { | ||
super(errorCode.getMessage()); | ||
this.httpStatus = errorCode.getStatus(); | ||
this.code = errorCode.getCode(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.depromeet.spot.common.exception; | ||
|
||
import org.springframework.http.HttpStatus; | ||
|
||
public interface ErrorCode { | ||
|
||
HttpStatus getStatus(); | ||
|
||
String getCode(); | ||
|
||
String getMessage(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package org.depromeet.spot.common.exception.member; | ||
|
||
import org.depromeet.spot.common.exception.ErrorCode; | ||
import org.springframework.http.HttpStatus; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public enum MemberErrorCode implements ErrorCode { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. custom error를 만들어야 한다면, 이런식으로 ErrorCode를 구현하는 enum 클래스를 새로 생성하면 돼요. |
||
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "M001", "요청 유저가 존재하지 않습니다."), | ||
; | ||
|
||
private final HttpStatus status; | ||
private final String code; | ||
private String message; | ||
|
||
MemberErrorCode(HttpStatus status, String code, String message) { | ||
this.status = status; | ||
this.code = code; | ||
this.message = message; | ||
} | ||
|
||
public MemberErrorCode appended(Object o) { | ||
message = message + " {" + o.toString() + "}"; | ||
return this; | ||
} | ||
Comment on lines
+23
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정해진 메세지 외에 추가로 정보를 제공하고 싶을 수 있어요. 그때 사용하는 메서드에요. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package org.depromeet.spot.common.exception.member; | ||
|
||
import org.depromeet.spot.common.exception.BusinessException; | ||
|
||
public abstract class MemberException extends BusinessException { | ||
|
||
protected MemberException(MemberErrorCode errorCode) { | ||
super(errorCode); | ||
} | ||
|
||
public static class MemberNotFoundException extends MemberException { | ||
public MemberNotFoundException() { | ||
super(MemberErrorCode.MEMBER_NOT_FOUND); | ||
} | ||
|
||
public MemberNotFoundException(Object o) { | ||
super(MemberErrorCode.MEMBER_NOT_FOUND.appended(o)); | ||
} | ||
Comment on lines
+12
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 단순 예시..! (e.g., 특정 name에 해당하는 유저가 없을 경우, name : {string}을 message에 추가하는 등) |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
dependencies { | ||
implementation(project(":common")) | ||
implementation(project(":domain")) | ||
|
||
// spring | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
모든 도메인의 errorCode가 하나의 enum class에서 관리되면, 클래스가 너무 커져서 관리하기 힘들거라고 생각했어요.
(e.g., 200개의 error code 중에서 member와 관련된 error들을 찾는 상상..)
따라서 공통 포맷을 인터페이스로 만들고, 도메인별로 errorCode를 구현하게 처리해 응집도를 높였어요.