Skip to content

Commit

Permalink
[BSVR-63] custom exception & global exception handler 추가 (#15)
Browse files Browse the repository at this point in the history
* feat: common 모듈 추가 및 errorCode enum 생성

* feat: spot application global exception handler 추가

* feat: custom exception 예제 코드 추가

* feat: 예제 수정

* feat: gitignore에 docker db 추가
  • Loading branch information
EunjiShin authored Jul 5, 2024
1 parent eca8047 commit 36ae2b3
Show file tree
Hide file tree
Showing 14 changed files with 175 additions and 5 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,5 @@ gradle-app.setting
# Java heap dump
*.hprof

# End of https://www.toptal.com/developers/gitignore/api/macos,windows,intellij,intellij+iml,intellij+all,visualstudiocode,java,gradle,kotlin
# End of https://www.toptal.com/developers/gitignore/api/macos,windows,intellij,intellij+iml,intellij+all,visualstudiocode,java,gradle,kotlin
/db/
1 change: 1 addition & 0 deletions application/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dependencies {
implementation(project(":common"))
implementation(project(":domain"))
implementation(project(":usecase"))
implementation(project(":infrastructure:jpa"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.depromeet.spot.application.config;
package org.depromeet.spot.application.common.config;

import org.depromeet.spot.jpa.config.JpaConfig;
import org.depromeet.spot.usecase.config.UsecaseConfig;
Expand Down
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);
}
}
42 changes: 42 additions & 0 deletions common/.gitignore
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
6 changes: 6 additions & 0 deletions common/build.gradle.kts
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 {
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;
}
}
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));
}
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ include("infrastructure")
include("infrastructure:jpa")
findProject(":infrastructure:jpa")?.name = "jpa"
include("usecase")
include("common")
1 change: 1 addition & 0 deletions usecase/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dependencies {
implementation(project(":common"))
implementation(project(":domain"))

// spring
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import java.util.List;

import org.depromeet.spot.common.exception.member.MemberException.MemberNotFoundException;
import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.usecase.port.in.MemberUsecase;
import org.depromeet.spot.usecase.port.out.MemberRepository;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import lombok.val;

@Service
@RequiredArgsConstructor
Expand All @@ -18,12 +18,16 @@ public class MemberService implements MemberUsecase {

@Override
public Member create(final String name) {
val member = new Member(null, name);
var member = new Member(null, name);
return memberRepository.save(member);
}

@Override
public List<Member> findByName(final String name) {
return memberRepository.findByName(name);
var members = memberRepository.findByName(name);
if (members.isEmpty()) {
throw new MemberNotFoundException("name : " + name);
}
return members;
}
}

0 comments on commit 36ae2b3

Please sign in to comment.