diff --git a/src/main/java/com/retrip/crew/domain/entity/Announcement.java b/src/main/java/com/retrip/crew/domain/entity/Announcement.java index ca4def9..694a274 100644 --- a/src/main/java/com/retrip/crew/domain/entity/Announcement.java +++ b/src/main/java/com/retrip/crew/domain/entity/Announcement.java @@ -2,7 +2,6 @@ import com.retrip.crew.domain.vo.AnnouncementContent; import com.retrip.crew.domain.vo.AnnouncementTitle; -import com.retrip.crew.domain.vo.NotificationBoardContent; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; diff --git a/src/main/java/com/retrip/crew/domain/exception/AnnouncementContentException.java b/src/main/java/com/retrip/crew/domain/exception/AnnouncementContentException.java deleted file mode 100644 index 554d584..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/AnnouncementContentException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class AnnouncementContentException extends CrewException { - - public AnnouncementContentException(String message) { - super(CrewErrorCode.ANNOUNCEMENT_CONTENT_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/AnnouncementTitleException.java b/src/main/java/com/retrip/crew/domain/exception/AnnouncementTitleException.java deleted file mode 100644 index 571ae90..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/AnnouncementTitleException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class AnnouncementTitleException extends CrewException { - - public AnnouncementTitleException(String message) { - super(CrewErrorCode.ANNOUNCEMENT_TITLE_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/CrewDescriptionException.java b/src/main/java/com/retrip/crew/domain/exception/CrewDescriptionException.java deleted file mode 100644 index 04db44e..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/CrewDescriptionException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class CrewDescriptionException extends CrewException { - - public CrewDescriptionException(String message) { - super(CrewErrorCode.CREW_DESCRIPTION_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/CrewErrorCode.java b/src/main/java/com/retrip/crew/domain/exception/CrewErrorCode.java deleted file mode 100644 index d494b90..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/CrewErrorCode.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.retrip.crew.domain.exception; - -public enum CrewErrorCode { - CREW_TITLE_ERROR(1001), - CREW_DESCRIPTION_ERROR(1002), - POST_TITLE_ERROR(1003), - POST_CONTENT_ERROR(1004), - ANNOUNCEMENT_TITLE_ERROR(1005), - ANNOUNCEMENT_CONTENT_ERROR(1006), - INTRODUCTION_TITLE_ERROR(1007), - INTRODUCTION_CONTENT_ERROR(1008); - - private final int code; - CrewErrorCode(int code) { - this.code = code; - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/CrewException.java b/src/main/java/com/retrip/crew/domain/exception/CrewException.java deleted file mode 100644 index 6b851e9..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/CrewException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.retrip.crew.domain.exception; - -public abstract class CrewException extends RuntimeException { - private final CrewErrorCode errorCode; - - public CrewException(CrewErrorCode errorCode, String message) { - super(message); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/CrewNotFoundException.java b/src/main/java/com/retrip/crew/domain/exception/CrewNotFoundException.java new file mode 100644 index 0000000..002f158 --- /dev/null +++ b/src/main/java/com/retrip/crew/domain/exception/CrewNotFoundException.java @@ -0,0 +1,12 @@ +package com.retrip.crew.domain.exception; + +import com.retrip.crew.domain.exception.common.EntityNotFoundException; +import com.retrip.crew.domain.exception.common.ErrorCode; + +public class CrewNotFoundException extends EntityNotFoundException { + private static final ErrorCode errorCode = ErrorCode.CREW_NOT_FOUND; + + public CrewNotFoundException() { + super(errorCode); + } +} diff --git a/src/main/java/com/retrip/crew/domain/exception/CrewTitleException.java b/src/main/java/com/retrip/crew/domain/exception/CrewTitleException.java deleted file mode 100644 index ae1c0c1..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/CrewTitleException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class CrewTitleException extends CrewException { - public CrewTitleException(String message) { - super(CrewErrorCode.CREW_TITLE_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/IntroductionContentException.java b/src/main/java/com/retrip/crew/domain/exception/IntroductionContentException.java deleted file mode 100644 index ab07f4b..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/IntroductionContentException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class IntroductionContentException extends CrewException { - private static final int ERROR_CODE = 1003; - - public IntroductionContentException(String message) { - super(CrewErrorCode.INTRODUCTION_CONTENT_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/IntroductionTitleException.java b/src/main/java/com/retrip/crew/domain/exception/IntroductionTitleException.java deleted file mode 100644 index 6d7af3e..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/IntroductionTitleException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class IntroductionTitleException extends CrewException { - private static final int ERROR_CODE = 1003; - - public IntroductionTitleException(String message) { - super(CrewErrorCode.INTRODUCTION_TITLE_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/PostContentException.java b/src/main/java/com/retrip/crew/domain/exception/PostContentException.java deleted file mode 100644 index 997f665..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/PostContentException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class PostContentException extends CrewException { - - public PostContentException(String message) { - super(CrewErrorCode.POST_CONTENT_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/PostTitleException.java b/src/main/java/com/retrip/crew/domain/exception/PostTitleException.java deleted file mode 100644 index 64afe6c..0000000 --- a/src/main/java/com/retrip/crew/domain/exception/PostTitleException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.retrip.crew.domain.exception; - -public class PostTitleException extends CrewException { - - public PostTitleException(String message) { - super(CrewErrorCode.POST_TITLE_ERROR, message); - } -} diff --git a/src/main/java/com/retrip/crew/domain/exception/common/BusinessException.java b/src/main/java/com/retrip/crew/domain/exception/common/BusinessException.java new file mode 100644 index 0000000..ea05e90 --- /dev/null +++ b/src/main/java/com/retrip/crew/domain/exception/common/BusinessException.java @@ -0,0 +1,18 @@ +package com.retrip.crew.domain.exception.common; + +import lombok.Getter; + +@Getter +public class BusinessException extends RuntimeException { + private final ErrorCode errorCode; + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public BusinessException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/com/retrip/crew/domain/exception/common/EntityNotFoundException.java b/src/main/java/com/retrip/crew/domain/exception/common/EntityNotFoundException.java new file mode 100644 index 0000000..2c6d127 --- /dev/null +++ b/src/main/java/com/retrip/crew/domain/exception/common/EntityNotFoundException.java @@ -0,0 +1,16 @@ +package com.retrip.crew.domain.exception.common; + +public class EntityNotFoundException extends BusinessException { + private static final ErrorCode errorCode = ErrorCode.ENTITY_NOT_FOUND; + public EntityNotFoundException(ErrorCode errorCode) { + super(errorCode); + } + + public EntityNotFoundException(String message) { + super(errorCode, message); + } + + public EntityNotFoundException(ErrorCode errorCode, String message) { + super(errorCode, message); + } +} diff --git a/src/main/java/com/retrip/crew/domain/exception/common/ErrorCode.java b/src/main/java/com/retrip/crew/domain/exception/common/ErrorCode.java new file mode 100644 index 0000000..520a72c --- /dev/null +++ b/src/main/java/com/retrip/crew/domain/exception/common/ErrorCode.java @@ -0,0 +1,27 @@ +package com.retrip.crew.domain.exception.common; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.*; + +@Getter +public enum ErrorCode { + SERVER_ERROR(INTERNAL_SERVER_ERROR, "Common-001", "Server error"), + INVALID_INPUT_VALUE(BAD_REQUEST, "Common-002", "Invalid input value"), + HANDLE_ACCESS_DENIED(FORBIDDEN, "Common-003", "Access is denied"), + ENTITY_NOT_FOUND(BAD_REQUEST, "Common-004", "Entity not found"), + + CREW_NOT_FOUND(BAD_REQUEST, "Crew-001", "크루 엔티티를 찾을 수 없습니다.") + ; + + private final HttpStatus status; + private final String code; + private final String message; + + ErrorCode(HttpStatus status, String code, String message) { + this.status = status; + this.code = code; + this.message = message; + } +} diff --git a/src/main/java/com/retrip/crew/domain/exception/common/InvalidValueException.java b/src/main/java/com/retrip/crew/domain/exception/common/InvalidValueException.java new file mode 100644 index 0000000..546de82 --- /dev/null +++ b/src/main/java/com/retrip/crew/domain/exception/common/InvalidValueException.java @@ -0,0 +1,17 @@ +package com.retrip.crew.domain.exception.common; + +public class InvalidValueException extends BusinessException { + private static final ErrorCode errorCode = ErrorCode.INVALID_INPUT_VALUE; + public InvalidValueException(ErrorCode errorCode) { + super(errorCode); + } + + public InvalidValueException(String message) { + super(errorCode, message); + } + + public InvalidValueException(ErrorCode errorCode, String message) { + super(errorCode, message); + } + +} diff --git a/src/main/java/com/retrip/crew/domain/vo/AnnouncementContent.java b/src/main/java/com/retrip/crew/domain/vo/AnnouncementContent.java index e213e0d..5d67c0f 100644 --- a/src/main/java/com/retrip/crew/domain/vo/AnnouncementContent.java +++ b/src/main/java/com/retrip/crew/domain/vo/AnnouncementContent.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewDescriptionException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public AnnouncementContent(String value) { private void validate(String value) { if (value.length() > CONTENT_LENGTH_LIMIT) { - throw new CrewDescriptionException("공지 게시글 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("공지 게시글 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/AnnouncementTitle.java b/src/main/java/com/retrip/crew/domain/vo/AnnouncementTitle.java index 7aabaf1..db5aa3e 100644 --- a/src/main/java/com/retrip/crew/domain/vo/AnnouncementTitle.java +++ b/src/main/java/com/retrip/crew/domain/vo/AnnouncementTitle.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.IntroductionTitleException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public AnnouncementTitle(String value) { private void validate(String value) { if (value.length() > TITLE_LENGTH_LIMIT) { - throw new IntroductionTitleException("공지 게시글 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("공지 게시글 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/CrewDescription.java b/src/main/java/com/retrip/crew/domain/vo/CrewDescription.java index 76c0eb9..e6789b5 100644 --- a/src/main/java/com/retrip/crew/domain/vo/CrewDescription.java +++ b/src/main/java/com/retrip/crew/domain/vo/CrewDescription.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewDescriptionException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public CrewDescription(String value) { private void validate(String value) { if (value.length() > DESCRIPTION_LENGTH_LIMIT) { - throw new CrewDescriptionException("크루 상세 설명은 " + DESCRIPTION_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("크루 상세 설명은 " + DESCRIPTION_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/CrewTitle.java b/src/main/java/com/retrip/crew/domain/vo/CrewTitle.java index 50cdbac..149ff6d 100644 --- a/src/main/java/com/retrip/crew/domain/vo/CrewTitle.java +++ b/src/main/java/com/retrip/crew/domain/vo/CrewTitle.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewTitleException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public CrewTitle(String value) { private void validate(String value) { if (value.length() > TITLE_LENGTH_LIMIT) { - throw new CrewTitleException("크루 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("크루 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/IntroductionContent.java b/src/main/java/com/retrip/crew/domain/vo/IntroductionContent.java index 6001175..0ffd8b3 100644 --- a/src/main/java/com/retrip/crew/domain/vo/IntroductionContent.java +++ b/src/main/java/com/retrip/crew/domain/vo/IntroductionContent.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewDescriptionException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public IntroductionContent(String value) { private void validate(String value) { if (value.length() > CONTENT_LENGTH_LIMIT) { - throw new CrewDescriptionException("자기 소개 게시글 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("자기 소개 게시글 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/IntroductionTitle.java b/src/main/java/com/retrip/crew/domain/vo/IntroductionTitle.java index 7668e76..5b06b18 100644 --- a/src/main/java/com/retrip/crew/domain/vo/IntroductionTitle.java +++ b/src/main/java/com/retrip/crew/domain/vo/IntroductionTitle.java @@ -1,7 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewTitleException; -import com.retrip.crew.domain.exception.IntroductionTitleException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -26,7 +25,7 @@ public IntroductionTitle(String value) { private void validate(String value) { if (value.length() > TITLE_LENGTH_LIMIT) { - throw new IntroductionTitleException("자기 소개 게시글 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("자기 소개 게시글 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/NotificationBoardContent.java b/src/main/java/com/retrip/crew/domain/vo/NotificationBoardContent.java deleted file mode 100644 index eeb7017..0000000 --- a/src/main/java/com/retrip/crew/domain/vo/NotificationBoardContent.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.retrip.crew.domain.vo; - -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Embeddable -@EqualsAndHashCode -@NoArgsConstructor(access = AccessLevel.PROTECTED, force = true) -public class NotificationBoardContent { - private static final int TITLE_LENGTH_LIMIT = 30; - private static final int CONTENT_LENGTH_LIMIT = 100; - - @Column(name = "title", nullable = false, length = TITLE_LENGTH_LIMIT) - private final String title; - - @Column(name = "content", nullable = false, length = CONTENT_LENGTH_LIMIT) - private final String content; - - public NotificationBoardContent(String title, String content) { - validate(title, content); - this.title = title; - this.content = content; - } - - private void validate(String title, String content) { - if (title.length() > TITLE_LENGTH_LIMIT) { - throw new IllegalArgumentException("공지 게시글 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); - } - if (content.length() > CONTENT_LENGTH_LIMIT) { - throw new IllegalArgumentException("공지 게시글 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); - } - } -} diff --git a/src/main/java/com/retrip/crew/domain/vo/PostContent.java b/src/main/java/com/retrip/crew/domain/vo/PostContent.java index 65dcb15..bc57e38 100644 --- a/src/main/java/com/retrip/crew/domain/vo/PostContent.java +++ b/src/main/java/com/retrip/crew/domain/vo/PostContent.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewDescriptionException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public PostContent(String value) { private void validate(String value) { if (value.length() > CONTENT_LENGTH_LIMIT) { - throw new CrewDescriptionException("자유 게시판 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("자유 게시판 내용은 " + CONTENT_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/domain/vo/PostTitle.java b/src/main/java/com/retrip/crew/domain/vo/PostTitle.java index 5d2f757..7c9d4f6 100644 --- a/src/main/java/com/retrip/crew/domain/vo/PostTitle.java +++ b/src/main/java/com/retrip/crew/domain/vo/PostTitle.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.IntroductionTitleException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.AccessLevel; @@ -25,7 +25,7 @@ public PostTitle(String value) { private void validate(String value) { if (value.length() > TITLE_LENGTH_LIMIT) { - throw new IntroductionTitleException("자유 게시판 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); + throw new InvalidValueException("자유 게시판 제목은 " + TITLE_LENGTH_LIMIT + "자를 넘을 수 없습니다."); } } } diff --git a/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/CrewController.java b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/CrewController.java index 30171a9..94d47bd 100644 --- a/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/CrewController.java +++ b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/CrewController.java @@ -3,12 +3,17 @@ import com.retrip.crew.application.in.request.CrewCreateRequest; import com.retrip.crew.application.in.response.CrewCreateResponse; import com.retrip.crew.application.in.usecase.CreateCrewUseCase; +import com.retrip.crew.domain.exception.CrewNotFoundException; +import com.retrip.crew.domain.exception.common.ErrorCode; +import com.retrip.crew.domain.exception.common.InvalidValueException; +import com.retrip.crew.infra.adapter.in.presentation.rest.common.ApiResponse; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.net.URI; diff --git a/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ApiResponse.java b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ApiResponse.java new file mode 100644 index 0000000..b35985d --- /dev/null +++ b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ApiResponse.java @@ -0,0 +1,37 @@ +package com.retrip.crew.infra.adapter.in.presentation.rest.common; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.*; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class ApiResponse { + private boolean success; + private int status; + private String message; + private T data; + + public static ApiResponse created(T data) { + return success(data, CREATED); + } + + public static ApiResponse ok(T data) { + return success(data, OK); + } + + public static ApiResponse of(T data, HttpStatus status) { + return success(data, status); + } + + private static ApiResponse success(T data, HttpStatus status) { + return new ApiResponse<>(true, status.value(), status.getReasonPhrase(), data); + } + + public static ApiResponse of(ErrorResponse errorResponse) { + return new ApiResponse<>(false, errorResponse.getStatus(), valueOf(errorResponse.getStatus()).getReasonPhrase(), errorResponse); + } +} diff --git a/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ErrorResponse.java b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ErrorResponse.java new file mode 100644 index 0000000..d602a22 --- /dev/null +++ b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/ErrorResponse.java @@ -0,0 +1,37 @@ +package com.retrip.crew.infra.adapter.in.presentation.rest.common; + +import com.retrip.crew.domain.exception.common.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@AllArgsConstructor +public class ErrorResponse { + private int status; + private String code; + private String message; + private String url = "Not available"; + private String method; + private List errors = new ArrayList<>(); + + private ErrorResponse(int status, String code, String message, String url, String method) { + this.status = status; + this.code = code; + this.message = message; + this.url = url; + this.method = method; + } + + public static ErrorResponse of(ErrorCode code, String url, String method, BindingResult bindingResult) { + return new ErrorResponse(code.getStatus().value(), code.getCode(), code.getMessage(), url, method, bindingResult.getFieldErrors()); + } + + public static ErrorResponse of(ErrorCode code, String url, String method) { + return new ErrorResponse(code.getStatus().value(), code.getCode(), code.getMessage(), url, method); + } +} diff --git a/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/GlobalExceptionHandler.java b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/GlobalExceptionHandler.java new file mode 100644 index 0000000..bbd83cd --- /dev/null +++ b/src/main/java/com/retrip/crew/infra/adapter/in/presentation/rest/common/GlobalExceptionHandler.java @@ -0,0 +1,54 @@ +package com.retrip.crew.infra.adapter.in.presentation.rest.common; + +import com.retrip.crew.domain.exception.common.BusinessException; +import com.retrip.crew.domain.exception.common.ErrorCode; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.nio.file.AccessDeniedException; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(AccessDeniedException.class) + public ApiResponse handleAccessDeniedException(HttpServletRequest request, AccessDeniedException e) { + log.error("handleAccessDeniedException: ", e); + return handle(ErrorCode.HANDLE_ACCESS_DENIED, request); + } + + @ExceptionHandler(BindException.class) + public ApiResponse handleBindException(HttpServletRequest request, BindException e) { + log.error("handleBindException: ", e); + return ApiResponse.of( + ErrorResponse.of( + ErrorCode.INVALID_INPUT_VALUE, + request.getRequestURL().toString(), + request.getMethod(), + e.getBindingResult() + )); + } + + @ExceptionHandler(BusinessException.class) + public ApiResponse handleBusinessException(HttpServletRequest request, BusinessException e) { + log.error("handleBusinessException: ", e); + return handle(e.getErrorCode(), request); + } + + + @ExceptionHandler(Exception.class) + public ApiResponse handleException(HttpServletRequest request, Exception e) { + log.error("handleException: ", e); + return handle(ErrorCode.SERVER_ERROR, request); + } + + private static ApiResponse handle(ErrorCode errorCode, HttpServletRequest request) { + return ApiResponse.of( + ErrorResponse.of( + errorCode, request.getRequestURL().toString(), request.getMethod() + )); + } +} diff --git a/src/test/java/com/retrip/crew/domain/vo/CrewIntroductionTitleTest.java b/src/test/java/com/retrip/crew/domain/vo/CrewIntroductionTitleTest.java index 694e249..657c233 100644 --- a/src/test/java/com/retrip/crew/domain/vo/CrewIntroductionTitleTest.java +++ b/src/test/java/com/retrip/crew/domain/vo/CrewIntroductionTitleTest.java @@ -1,6 +1,6 @@ package com.retrip.crew.domain.vo; -import com.retrip.crew.domain.exception.CrewTitleException; +import com.retrip.crew.domain.exception.common.InvalidValueException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,6 +11,7 @@ class CrewIntroductionTitleTest { @Test @DisplayName("크루 이름은 30자 미만으로 설정해야한다.") public void validateName() { - assertThatThrownBy(() -> new CrewTitle("통천, 회양, 평강, 이천, 김화, 철원, 양구, 인제, 고성, 강릉, 속초 등 크루 인원 모집합니다.")).isExactlyInstanceOf(CrewTitleException.class); + assertThatThrownBy(() -> new CrewTitle("통천, 회양, 평강, 이천, 김화, 철원, 양구, 인제, 고성, 강릉, 속초 등 크루 인원 모집합니다.")) + .isExactlyInstanceOf(InvalidValueException.class); } }