From 3642ddb883427b2fa0fdeefe9438bb802e57d0f2 Mon Sep 17 00:00:00 2001 From: seungyeop-lee Date: Sun, 9 Jun 2024 13:01:07 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=EC=97=90=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20funnel=EA=B3=BC=20job=EC=9D=84=20enum=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20#69?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/data/CompleteOnboardingCommand.java | 10 ++++---- .../vook/server/api/model/user/Funnel.java | 24 +++++++++++++++++++ .../java/vook/server/api/model/user/Job.java | 24 +++++++++++++++++++ .../vook/server/api/model/user/UserInfo.java | 8 ++++--- .../common/GlobalRestControllerAdvice.java | 9 +++++++ .../server/api/web/routes/user/UserApi.java | 10 ++++++++ .../reqres/UserOnboardingCompleteRequest.java | 6 +++-- .../api/testhelper/TestDataCreator.java | 4 +++- .../web/routes/user/UserWebServiceTest.java | 6 +++-- 9 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 api/src/main/java/vook/server/api/model/user/Funnel.java create mode 100644 api/src/main/java/vook/server/api/model/user/Job.java diff --git a/api/src/main/java/vook/server/api/app/user/data/CompleteOnboardingCommand.java b/api/src/main/java/vook/server/api/app/user/data/CompleteOnboardingCommand.java index 3bce964..f8da1a5 100644 --- a/api/src/main/java/vook/server/api/app/user/data/CompleteOnboardingCommand.java +++ b/api/src/main/java/vook/server/api/app/user/data/CompleteOnboardingCommand.java @@ -1,18 +1,20 @@ package vook.server.api.app.user.data; import lombok.Getter; +import vook.server.api.model.user.Funnel; +import vook.server.api.model.user.Job; @Getter public class CompleteOnboardingCommand { public String userUid; - public String funnel; - public String job; + public Funnel funnel; + public Job job; public static CompleteOnboardingCommand of( String userUid, - String funnel, - String job + Funnel funnel, + Job job ) { CompleteOnboardingCommand command = new CompleteOnboardingCommand(); command.userUid = userUid; diff --git a/api/src/main/java/vook/server/api/model/user/Funnel.java b/api/src/main/java/vook/server/api/model/user/Funnel.java new file mode 100644 index 0000000..bce5fc3 --- /dev/null +++ b/api/src/main/java/vook/server/api/model/user/Funnel.java @@ -0,0 +1,24 @@ +package vook.server.api.model.user; + +public enum Funnel { + //X + X, + + //페이스북 + FACEBOOK, + + //링크드인 + LINKEDIN, + + //인스타그램 + INSTAGRAM, + + //네이버 블로그 + NAVER_BLOG, + + //친구/지인 추천 + RECOMMENDATION, + + //기타 + OTHER +} diff --git a/api/src/main/java/vook/server/api/model/user/Job.java b/api/src/main/java/vook/server/api/model/user/Job.java new file mode 100644 index 0000000..37dbdd3 --- /dev/null +++ b/api/src/main/java/vook/server/api/model/user/Job.java @@ -0,0 +1,24 @@ +package vook.server.api.model.user; + +public enum Job { + //기획자 + PLANNER, + + //디자이너 + DESIGNER, + + //개발자 + DEVELOPER, + + //마케터 + MARKETER, + + //CEO + CEO, + + //HR + HR, + + //기타 + OTHER +} diff --git a/api/src/main/java/vook/server/api/model/user/UserInfo.java b/api/src/main/java/vook/server/api/model/user/UserInfo.java index d0bffae..a3444a7 100644 --- a/api/src/main/java/vook/server/api/model/user/UserInfo.java +++ b/api/src/main/java/vook/server/api/model/user/UserInfo.java @@ -16,9 +16,11 @@ public class UserInfo { private Boolean marketingEmailOptIn; - private String funnel; + @Enumerated(EnumType.STRING) + private Funnel funnel; - private String job; + @Enumerated(EnumType.STRING) + private Job job; @OneToOne @JoinColumn(name = "user_id") @@ -36,7 +38,7 @@ public static UserInfo forRegisterOf( return result; } - public void addOnboardingInfo(String funnel, String job) { + public void addOnboardingInfo(Funnel funnel, Job job) { this.funnel = funnel; this.job = job; } diff --git a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java index 73f0d79..0c27133 100644 --- a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java +++ b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java @@ -2,6 +2,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -18,6 +19,14 @@ public ResponseEntity handleCommonApiException(CommonApiException.Exception e @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + log.debug(e.getMessage(), e); + CommonApiException.BadRequest badRequest = new CommonApiException.BadRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); + return ResponseEntity.status(badRequest.statusCode()).body(badRequest.response()); + } + + @ExceptionHandler(HttpMessageConversionException.class) + public ResponseEntity handleHttpMessageConversionException(HttpMessageConversionException e) { + log.debug(e.getMessage(), e); CommonApiException.BadRequest badRequest = new CommonApiException.BadRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); return ResponseEntity.status(badRequest.statusCode()).body(badRequest.response()); } diff --git a/api/src/main/java/vook/server/api/web/routes/user/UserApi.java b/api/src/main/java/vook/server/api/web/routes/user/UserApi.java index 2e2a005..e15959f 100644 --- a/api/src/main/java/vook/server/api/web/routes/user/UserApi.java +++ b/api/src/main/java/vook/server/api/web/routes/user/UserApi.java @@ -62,5 +62,15 @@ class UserApiUerInfoResponse extends CommonApiResponse { @SecurityRequirement(name = "AccessToken") } ) + @ApiResponses(value = { + @ApiResponse( + responseCode = "400", + content = @Content( + mediaType = "application/json", + schema = @Schema(ref = ComponentRefConsts.Schema.COMMON_API_RESPONSE), + examples = @ExampleObject(name = "유효하지 않은 파라미터", ref = ComponentRefConsts.Example.INVALID_PARAMETER) + ) + ), + }) CommonApiResponse onboardingComplete(VookLoginUser user, UserOnboardingCompleteRequest request); } diff --git a/api/src/main/java/vook/server/api/web/routes/user/reqres/UserOnboardingCompleteRequest.java b/api/src/main/java/vook/server/api/web/routes/user/reqres/UserOnboardingCompleteRequest.java index 4756bcd..994e50b 100644 --- a/api/src/main/java/vook/server/api/web/routes/user/reqres/UserOnboardingCompleteRequest.java +++ b/api/src/main/java/vook/server/api/web/routes/user/reqres/UserOnboardingCompleteRequest.java @@ -2,12 +2,14 @@ import lombok.Data; import vook.server.api.app.user.data.CompleteOnboardingCommand; +import vook.server.api.model.user.Funnel; +import vook.server.api.model.user.Job; @Data public class UserOnboardingCompleteRequest { - public String funnel; - public String job; + public Funnel funnel; + public Job job; public CompleteOnboardingCommand toCommand(String uid) { return CompleteOnboardingCommand.of(uid, funnel, job); diff --git a/api/src/test/java/vook/server/api/testhelper/TestDataCreator.java b/api/src/test/java/vook/server/api/testhelper/TestDataCreator.java index edcd7c8..272a7f4 100644 --- a/api/src/test/java/vook/server/api/testhelper/TestDataCreator.java +++ b/api/src/test/java/vook/server/api/testhelper/TestDataCreator.java @@ -7,6 +7,8 @@ import vook.server.api.app.user.data.CompleteOnboardingCommand; import vook.server.api.app.user.data.RegisterCommand; import vook.server.api.app.user.data.SignUpFromSocialCommand; +import vook.server.api.model.user.Funnel; +import vook.server.api.model.user.Job; import vook.server.api.model.user.SocialUser; import vook.server.api.model.user.User; import vook.server.api.web.auth.app.TokenService; @@ -35,7 +37,7 @@ public User createRegisteredUser() { public User createCompletedOnboardingUser() { User user = createRegisteredUser(); - userService.completeOnboarding(CompleteOnboardingCommand.of(user.getUid(), "testFunnel", "testJob")); + userService.completeOnboarding(CompleteOnboardingCommand.of(user.getUid(), Funnel.OTHER, Job.OTHER)); return userService.findByUid(user.getUid()).orElseThrow(); } diff --git a/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java b/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java index 6b9d489..7f3dc72 100644 --- a/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java +++ b/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java @@ -5,6 +5,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import vook.server.api.app.user.UserService; +import vook.server.api.model.user.Funnel; +import vook.server.api.model.user.Job; import vook.server.api.model.user.User; import vook.server.api.model.user.UserStatus; import vook.server.api.testhelper.IntegrationTestBase; @@ -112,8 +114,8 @@ void onboardingComplete1() { VookLoginUser vookLoginUser = VookLoginUser.of(registeredUser.getUid()); UserOnboardingCompleteRequest request = new UserOnboardingCompleteRequest(); - request.setFunnel("testFunnel"); - request.setJob("testJob"); + request.setFunnel(Funnel.OTHER); + request.setJob(Job.OTHER); // when userWebService.onboardingComplete(vookLoginUser, request); From de9fa6a5688f1f7117aec2fb200cce03d5e3267b Mon Sep 17 00:00:00 2001 From: seungyeop-lee Date: Sun, 9 Jun 2024 13:18:39 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20CommonApiException=20=EB=8B=A8?= =?UTF-8?q?=EC=88=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/web/common/CommonApiException.java | 56 ++++++------------- .../common/GlobalRestControllerAdvice.java | 10 ++-- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/api/src/main/java/vook/server/api/web/common/CommonApiException.java b/api/src/main/java/vook/server/api/web/common/CommonApiException.java index 2c01757..a4934b7 100644 --- a/api/src/main/java/vook/server/api/web/common/CommonApiException.java +++ b/api/src/main/java/vook/server/api/web/common/CommonApiException.java @@ -1,51 +1,29 @@ package vook.server.api.web.common; -public class CommonApiException { - public static abstract class Exception extends RuntimeException { +public class CommonApiException extends RuntimeException { - protected ApiResponseCode code; + private final ApiResponseCode code; + private final int statusCode; - public Exception(ApiResponseCode code, Throwable cause) { - super(code.code(), cause); - this.code = code; - } - - abstract CommonApiResponse response(); - - abstract int statusCode(); + CommonApiException(ApiResponseCode code, int statusCode, Throwable cause) { + super(code.code(), cause); + this.code = code; + this.statusCode = statusCode; } - public static class BadRequest extends Exception { - - public BadRequest(ApiResponseCode code, Throwable cause) { - super(code, cause); - } - - @Override - public CommonApiResponse response() { - return CommonApiResponse.noResult(code); - } - - @Override - int statusCode() { - return 400; - } + public CommonApiResponse response() { + return CommonApiResponse.noResult(code); } - public static class ServerError extends Exception { - - public ServerError(ApiResponseCode code, Throwable cause) { - super(code, cause); - } + public int statusCode() { + return statusCode; + } - @Override - public CommonApiResponse response() { - return CommonApiResponse.noResult(code); - } + public static CommonApiException badRequest(ApiResponseCode code, Throwable cause) { + return new CommonApiException(code, 400, cause); + } - @Override - int statusCode() { - return 500; - } + public static CommonApiException serverError(ApiResponseCode code, Throwable cause) { + return new CommonApiException(code, 500, cause); } } diff --git a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java index 0c27133..67ebd2c 100644 --- a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java +++ b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java @@ -11,8 +11,8 @@ @RestControllerAdvice public class GlobalRestControllerAdvice { - @ExceptionHandler(CommonApiException.Exception.class) - public ResponseEntity handleCommonApiException(CommonApiException.Exception e) { + @ExceptionHandler(CommonApiException.class) + public ResponseEntity handleCommonApiException(CommonApiException e) { log.error(e.getMessage(), e); return ResponseEntity.status(e.statusCode()).body(e.response()); } @@ -20,21 +20,21 @@ public ResponseEntity handleCommonApiException(CommonApiException.Exception e @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.debug(e.getMessage(), e); - CommonApiException.BadRequest badRequest = new CommonApiException.BadRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); + CommonApiException badRequest = CommonApiException.badRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); return ResponseEntity.status(badRequest.statusCode()).body(badRequest.response()); } @ExceptionHandler(HttpMessageConversionException.class) public ResponseEntity handleHttpMessageConversionException(HttpMessageConversionException e) { log.debug(e.getMessage(), e); - CommonApiException.BadRequest badRequest = new CommonApiException.BadRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); + CommonApiException badRequest = CommonApiException.badRequest(ApiResponseCode.BadRequest.INVALID_PARAMETER, e); return ResponseEntity.status(badRequest.statusCode()).body(badRequest.response()); } @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception e) { log.error(e.getMessage(), e); - CommonApiException.ServerError serverError = new CommonApiException.ServerError(ApiResponseCode.ServerError.UNHANDLED_ERROR, e); + CommonApiException serverError = CommonApiException.serverError(ApiResponseCode.ServerError.UNHANDLED_ERROR, e); return ResponseEntity.status(serverError.statusCode()).body(serverError.response()); } } From de7d24a2dd6b31e724e4d395db440de32a202849 Mon Sep 17 00:00:00 2001 From: seungyeop-lee Date: Sun, 9 Jun 2024 13:27:45 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EB=AF=B8=EA=B0=80=EC=9E=85?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EA=B0=80=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=EB=A5=BC=20=EC=8B=9C=EB=8F=84=20=ED=95=A0=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0,=20=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20#69?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vook/server/api/app/user/UserService.java | 5 +++++ .../NotReadyToOnboardingException.java | 4 ++++ .../java/vook/server/api/model/user/User.java | 4 ++++ .../web/routes/user/UserWebServiceTest.java | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java diff --git a/api/src/main/java/vook/server/api/app/user/UserService.java b/api/src/main/java/vook/server/api/app/user/UserService.java index 6ec626e..2e70995 100644 --- a/api/src/main/java/vook/server/api/app/user/UserService.java +++ b/api/src/main/java/vook/server/api/app/user/UserService.java @@ -5,6 +5,7 @@ import vook.server.api.app.user.data.CompleteOnboardingCommand; import vook.server.api.app.user.data.RegisterCommand; import vook.server.api.app.user.data.SignUpFromSocialCommand; +import vook.server.api.app.user.exception.NotReadyToOnboardingException; import vook.server.api.app.user.repo.SocialUserRepository; import vook.server.api.app.user.repo.UserInfoRepository; import vook.server.api.app.user.repo.UserRepository; @@ -57,6 +58,10 @@ public void register(RegisterCommand command) { public void completeOnboarding(CompleteOnboardingCommand command) { User user = repository.findByUid(command.getUserUid()).orElseThrow(); + if (!user.isReadyToOnboarding()) { + throw new NotReadyToOnboardingException(); + } + user.onboardingCompleted(); user.getUserInfo().addOnboardingInfo(command.getFunnel(), command.getJob()); diff --git a/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java b/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java new file mode 100644 index 0000000..072078a --- /dev/null +++ b/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java @@ -0,0 +1,4 @@ +package vook.server.api.app.user.exception; + +public class NotReadyToOnboardingException extends RuntimeException { +} diff --git a/api/src/main/java/vook/server/api/model/user/User.java b/api/src/main/java/vook/server/api/model/user/User.java index cfa454b..7115ecf 100644 --- a/api/src/main/java/vook/server/api/model/user/User.java +++ b/api/src/main/java/vook/server/api/model/user/User.java @@ -58,4 +58,8 @@ public void registered() { public void onboardingCompleted() { this.status = UserStatus.ONBOARDING_COMPLETED; } + + public boolean isReadyToOnboarding() { + return status == UserStatus.REGISTERED; + } } diff --git a/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java b/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java index 7f3dc72..f32684d 100644 --- a/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java +++ b/api/src/test/java/vook/server/api/web/routes/user/UserWebServiceTest.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import vook.server.api.app.user.UserService; +import vook.server.api.app.user.exception.NotReadyToOnboardingException; import vook.server.api.model.user.Funnel; import vook.server.api.model.user.Job; import vook.server.api.model.user.User; @@ -17,6 +18,7 @@ import vook.server.api.web.routes.user.reqres.UserRegisterRequest; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; @Transactional class UserWebServiceTest extends IntegrationTestBase { @@ -127,4 +129,20 @@ void onboardingComplete1() { assertThat(user.getUserInfo().getFunnel()).isEqualTo(request.getFunnel()); assertThat(user.getUserInfo().getJob()).isEqualTo(request.getJob()); } + + @Test + @DisplayName("온보딩 완료 - 에러; 미 가입 유저") + void onboardingCompleteError1() { + // given + User unregisteredUser = testDataCreator.createUnregisteredUser(); + VookLoginUser vookLoginUser = VookLoginUser.of(unregisteredUser.getUid()); + + UserOnboardingCompleteRequest request = new UserOnboardingCompleteRequest(); + request.setFunnel(Funnel.OTHER); + request.setJob(Job.OTHER); + + // when + assertThatThrownBy(() -> userWebService.onboardingComplete(vookLoginUser, request)) + .isInstanceOf(NotReadyToOnboardingException.class); + } } From b83e4d479cb93e8c796fe797fa66797170a45bf2 Mon Sep 17 00:00:00 2001 From: seungyeop-lee Date: Sun, 9 Jun 2024 14:05:37 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EA=B7=9C=EC=B9=99=20=EC=9C=84=EB=B0=98=20API=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vook/server/api/app/common/AppException.java | 8 ++++++++ .../exception/NotReadyToOnboardingException.java | 9 ++++++++- .../server/api/web/common/ApiResponseCode.java | 4 +++- .../api/web/common/CommonApiException.java | 16 +++++++++++++++- .../web/common/GlobalRestControllerAdvice.java | 8 ++++++++ .../vook/server/api/web/routes/user/UserApi.java | 5 ++++- .../api/web/swagger/ComponentRefConsts.java | 1 + .../web/swagger/GlobalOpenApiCustomizerImpl.java | 8 ++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 api/src/main/java/vook/server/api/app/common/AppException.java diff --git a/api/src/main/java/vook/server/api/app/common/AppException.java b/api/src/main/java/vook/server/api/app/common/AppException.java new file mode 100644 index 0000000..80ac452 --- /dev/null +++ b/api/src/main/java/vook/server/api/app/common/AppException.java @@ -0,0 +1,8 @@ +package vook.server.api.app.common; + +import lombok.Getter; + +@Getter +public abstract class AppException extends RuntimeException { + public abstract String contents(); +} diff --git a/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java b/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java index 072078a..0cba64e 100644 --- a/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java +++ b/api/src/main/java/vook/server/api/app/user/exception/NotReadyToOnboardingException.java @@ -1,4 +1,11 @@ package vook.server.api.app.user.exception; -public class NotReadyToOnboardingException extends RuntimeException { +import vook.server.api.app.common.AppException; + +public class NotReadyToOnboardingException extends AppException { + + @Override + public String contents() { + return "NotReadyToOnboarding"; + } } diff --git a/api/src/main/java/vook/server/api/web/common/ApiResponseCode.java b/api/src/main/java/vook/server/api/web/common/ApiResponseCode.java index 8d3d231..65205ce 100644 --- a/api/src/main/java/vook/server/api/web/common/ApiResponseCode.java +++ b/api/src/main/java/vook/server/api/web/common/ApiResponseCode.java @@ -16,7 +16,9 @@ public String code() { enum BadRequest implements ApiResponseCode { - INVALID_PARAMETER; + INVALID_PARAMETER, + VIOLATION_BUSINESS_RULE, + ; @Override public String code() { diff --git a/api/src/main/java/vook/server/api/web/common/CommonApiException.java b/api/src/main/java/vook/server/api/web/common/CommonApiException.java index a4934b7..f8ae152 100644 --- a/api/src/main/java/vook/server/api/web/common/CommonApiException.java +++ b/api/src/main/java/vook/server/api/web/common/CommonApiException.java @@ -4,15 +4,25 @@ public class CommonApiException extends RuntimeException { private final ApiResponseCode code; private final int statusCode; + private final String message; CommonApiException(ApiResponseCode code, int statusCode, Throwable cause) { + this(code, statusCode, cause, null); + } + + CommonApiException(ApiResponseCode code, int statusCode, Throwable cause, String message) { super(code.code(), cause); this.code = code; this.statusCode = statusCode; + this.message = message; } public CommonApiResponse response() { - return CommonApiResponse.noResult(code); + if (message == null) { + return CommonApiResponse.noResult(code); + } else { + return CommonApiResponse.withResult(code, message); + } } public int statusCode() { @@ -23,6 +33,10 @@ public static CommonApiException badRequest(ApiResponseCode code, Throwable caus return new CommonApiException(code, 400, cause); } + public static CommonApiException badRequest(ApiResponseCode code, Throwable cause, String message) { + return new CommonApiException(code, 400, cause, message); + } + public static CommonApiException serverError(ApiResponseCode code, Throwable cause) { return new CommonApiException(code, 500, cause); } diff --git a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java index 67ebd2c..5498c58 100644 --- a/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java +++ b/api/src/main/java/vook/server/api/web/common/GlobalRestControllerAdvice.java @@ -6,11 +6,19 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import vook.server.api.app.common.AppException; @Slf4j @RestControllerAdvice public class GlobalRestControllerAdvice { + @ExceptionHandler(AppException.class) + public ResponseEntity handleAppException(AppException e) { + log.error(e.getMessage(), e); + CommonApiException badRequest = CommonApiException.badRequest(ApiResponseCode.BadRequest.VIOLATION_BUSINESS_RULE, e, e.contents()); + return ResponseEntity.status(badRequest.statusCode()).body(badRequest.response()); + } + @ExceptionHandler(CommonApiException.class) public ResponseEntity handleCommonApiException(CommonApiException e) { log.error(e.getMessage(), e); diff --git a/api/src/main/java/vook/server/api/web/routes/user/UserApi.java b/api/src/main/java/vook/server/api/web/routes/user/UserApi.java index e15959f..5c95833 100644 --- a/api/src/main/java/vook/server/api/web/routes/user/UserApi.java +++ b/api/src/main/java/vook/server/api/web/routes/user/UserApi.java @@ -68,7 +68,10 @@ class UserApiUerInfoResponse extends CommonApiResponse { content = @Content( mediaType = "application/json", schema = @Schema(ref = ComponentRefConsts.Schema.COMMON_API_RESPONSE), - examples = @ExampleObject(name = "유효하지 않은 파라미터", ref = ComponentRefConsts.Example.INVALID_PARAMETER) + examples = { + @ExampleObject(name = "유효하지 않은 파라미터", ref = ComponentRefConsts.Example.INVALID_PARAMETER), + @ExampleObject(name = "비즈니스 규칙 위반", ref = ComponentRefConsts.Example.VIOLATION_BUSINESS_RULE) + } ) ), }) diff --git a/api/src/main/java/vook/server/api/web/swagger/ComponentRefConsts.java b/api/src/main/java/vook/server/api/web/swagger/ComponentRefConsts.java index 12890cc..ec32603 100644 --- a/api/src/main/java/vook/server/api/web/swagger/ComponentRefConsts.java +++ b/api/src/main/java/vook/server/api/web/swagger/ComponentRefConsts.java @@ -13,5 +13,6 @@ public static class Example { public static final String SUCCESS = "#/components/examples/Success"; public static final String INVALID_PARAMETER = "#/components/examples/InvalidParameter"; public static final String UNHANDLED_ERROR = "#/components/examples/UnhandledError"; + public static final String VIOLATION_BUSINESS_RULE = "#/components/examples/ViolationBusinessRule"; } } diff --git a/api/src/main/java/vook/server/api/web/swagger/GlobalOpenApiCustomizerImpl.java b/api/src/main/java/vook/server/api/web/swagger/GlobalOpenApiCustomizerImpl.java index 1347211..3554438 100644 --- a/api/src/main/java/vook/server/api/web/swagger/GlobalOpenApiCustomizerImpl.java +++ b/api/src/main/java/vook/server/api/web/swagger/GlobalOpenApiCustomizerImpl.java @@ -35,6 +35,14 @@ private static void applyCommonApiResponseSchema(OpenAPI openApi) { "code": "%s" }""", ApiResponseCode.BadRequest.INVALID_PARAMETER.code())) ) + .addExamples(getKey(ComponentRefConsts.Example.VIOLATION_BUSINESS_RULE), new Example() + .description("비즈니스 규칙 위반") + .value(String.format(""" + { + "code": "%s", + "result": "규칙 위반 내용 (ex. NotReadyToOnboarding)" + }""", ApiResponseCode.BadRequest.VIOLATION_BUSINESS_RULE.code())) + ) .addExamples(getKey(ComponentRefConsts.Example.UNHANDLED_ERROR), new Example() .description("처리되지 않은 서버 에러") .value(String.format("""