From 2c1fdb70b5ce1c56e1659c10751e1bfe039e6b94 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Tue, 2 Jan 2024 20:36:54 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=9C=20problme=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 ++ .../global/exception/InvalidResponse.java | 21 +++++++++++++++++++ src/main/resources/application.yml | 5 +++++ 3 files changed, 28 insertions(+) create mode 100644 src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java diff --git a/build.gradle.kts b/build.gradle.kts index 28287c7..cdda6c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,6 +44,8 @@ dependencies { developmentOnly("org.springframework.boot:spring-boot-devtools") testImplementation("org.springframework.boot:spring-boot-starter-test") + + implementation("org.zalando:problem-spring-web-starter:0.27.0") } tasks.withType { diff --git a/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java b/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java new file mode 100644 index 0000000..f795799 --- /dev/null +++ b/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java @@ -0,0 +1,21 @@ +package org.idiot.yesslave.global.exception; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +@AllArgsConstructor +@Schema(description = "유효성 검사에 실패했을 경우의 RESPONSE") +public class InvalidResponse { + @Schema(description = "오류 발생 field명", example = "mobileNo") + String field; + + @Schema(description = "오류 발생 field명", example = "휴대전화번호을 입력해주세요.") + String message; + + @Schema(description = "오류 발생 field 입력 값", example = "AAA") + Object rejectValue; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8105739..f0953f7 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,3 +15,8 @@ spring: format_sql: true show_sql: true dialect: org.hibernate.dialect.MySQL8Dialect + web: + resources: + add-mappings: false + mvc: + throw-exception-if-no-handler-found: true \ No newline at end of file From 279e1c5af8762681a9085bf7121d416c3f5340a1 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Tue, 2 Jan 2024 20:37:12 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20500=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/RootExceptionHandler.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java diff --git a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java new file mode 100644 index 0000000..7c7f6d5 --- /dev/null +++ b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java @@ -0,0 +1,40 @@ +package org.idiot.yesslave.global.exception; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.zalando.problem.Problem; +import org.zalando.problem.spring.web.advice.ProblemHandling; + +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; + +@Slf4j +@ControllerAdvice +//@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) +public class RootExceptionHandler implements ProblemHandling { + @ExceptionHandler(Exception.class) + @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = { + @Content(schema = @Schema(implementation = Problem.class)) + }) + public ResponseEntity exceptionHandler(Exception e) { + + log.error("[ 500 ERROR ] : ", e); + + Problem problem = Problem.builder() + .withStatus(INTERNAL_SERVER_ERROR) + .withTitle(INTERNAL_SERVER_ERROR.getReasonPhrase()) + .withDetail(e.getMessage()) + .build(); + + return ResponseEntity + .status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(problem); + } +} From 42685793711757c6f1cc81ed8c22d5aab455e9d1 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Tue, 2 Jan 2024 23:15:54 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=97=90=20=EC=8B=A4=ED=8C=A8=ED=95=9C=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EA=B4=80=EB=A0=A8=20400=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + .../global/exception/InvalidResponse.java | 16 +++-- .../exception/RootExceptionHandler.java | 62 ++++++++++++++++++- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index cdda6c7..83328ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,6 +46,7 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") implementation("org.zalando:problem-spring-web-starter:0.27.0") + implementation("org.springframework.boot:spring-boot-starter-validation") } tasks.withType { diff --git a/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java b/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java index f795799..53ee574 100644 --- a/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java +++ b/src/main/java/org/idiot/yesslave/global/exception/InvalidResponse.java @@ -3,19 +3,17 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.ToString; @Getter -@ToString @AllArgsConstructor -@Schema(description = "유효성 검사에 실패했을 경우의 RESPONSE") +@Schema(description = "입력된 값에 대한 유효성 검사에 실패했을 경우의 응답값") public class InvalidResponse { - @Schema(description = "오류 발생 field명", example = "mobileNo") - String field; + @Schema(description = "오류가 발생한 field명", example = "verificationCode") + private String field; - @Schema(description = "오류 발생 field명", example = "휴대전화번호을 입력해주세요.") - String message; + @Schema(description = "오류 메세지", example = "확인번호를 입력해주세요.") + private String message; - @Schema(description = "오류 발생 field 입력 값", example = "AAA") - Object rejectValue; + @Schema(description = "잘못 입력된 field 입력 값", example = "ABCDE") + private Object rejectValue; } diff --git a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java index 7c7f6d5..b5e1bf7 100644 --- a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java +++ b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java @@ -4,20 +4,28 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.ProblemHandling; +import javax.validation.ConstraintViolationException; +import java.util.ArrayList; +import java.util.List; + +import static org.zalando.problem.Status.BAD_REQUEST; import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; @Slf4j @ControllerAdvice -//@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) -public class RootExceptionHandler implements ProblemHandling { +@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) +public class RootExceptionHandler { @ExceptionHandler(Exception.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ApiResponse(responseCode = "500", description = "Internal Server Error", content = { @@ -37,4 +45,52 @@ public ResponseEntity exceptionHandler(Exception e) { .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(problem); } + + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ApiResponse(responseCode = "400", description = "Bad Request", content = { + @Content(schema = @Schema(implementation = InvalidResponse.class)) + }) + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { + log.error("[ 400 ERROR ] : ", e); + + BindingResult bindingResult = e.getBindingResult(); + + List responses = new ArrayList<>(); + + bindingResult.getFieldErrors().forEach(fieldError -> { + responses.add(new InvalidResponse(fieldError.getField(), fieldError.getDefaultMessage(), fieldError.getRejectedValue())); + }); + + Problem problem = Problem.builder() + .withStatus(BAD_REQUEST) + .withTitle(BAD_REQUEST.getReasonPhrase()) + .with("parameters", responses) + .build(); + + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(problem); + } + + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ApiResponse(responseCode = "400", description = "Bad Request", content = { + @Content(schema = @Schema(implementation = InvalidResponse.class)) + }) + @ExceptionHandler(ConstraintViolationException.class) + public Problem constraintViolationExceptionHandler(ConstraintViolationException e) { + log.error("[ 400 ERROR ] : ", e); + + List responses = new ArrayList<>(); + + e.getConstraintViolations().forEach(fieldError -> { + responses.add(new InvalidResponse(fieldError.getPropertyPath().toString(), fieldError.getMessage(), fieldError.getInvalidValue())); + }); + + return Problem.builder() + .withStatus(BAD_REQUEST) + .withTitle(BAD_REQUEST.getReasonPhrase()) + .with("parameters", responses) + .build(); + } } From e4ee5e73e2109705df80468bf8d6b85dc1a7c2b5 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Tue, 2 Jan 2024 23:20:16 +0900 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20=EB=A7=88=EC=A7=80=EB=A7=89=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f0953f7..49b0d07 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -19,4 +19,5 @@ spring: resources: add-mappings: false mvc: - throw-exception-if-no-handler-found: true \ No newline at end of file + throw-exception-if-no-handler-found: true + \ No newline at end of file From d192e0a265aee3ce3745aa7581c2fe41df12e832 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Fri, 5 Jan 2024 01:01:44 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20build.gradle=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 83328ac..554b34c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,6 +26,9 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-validation") + + developmentOnly("org.springframework.boot:spring-boot-devtools") //flyway implementation("org.flywaydb:flyway-core") @@ -42,11 +45,11 @@ dependencies { compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") - developmentOnly("org.springframework.boot:spring-boot-devtools") - testImplementation("org.springframework.boot:spring-boot-starter-test") - + //problem implementation("org.zalando:problem-spring-web-starter:0.27.0") - implementation("org.springframework.boot:spring-boot-starter-validation") + + //test + testImplementation("org.springframework.boot:spring-boot-starter-test") } tasks.withType { From 47714250448e1ca249ceca74b363f20ad8126f57 Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Fri, 5 Jan 2024 01:04:13 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20Status=20import=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/exception/RootExceptionHandler.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java index b5e1bf7..c84abd1 100644 --- a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java +++ b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java @@ -14,14 +14,12 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.zalando.problem.Problem; +import org.zalando.problem.Status; import javax.validation.ConstraintViolationException; import java.util.ArrayList; import java.util.List; -import static org.zalando.problem.Status.BAD_REQUEST; -import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; - @Slf4j @ControllerAdvice @EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) @@ -36,8 +34,8 @@ public ResponseEntity exceptionHandler(Exception e) { log.error("[ 500 ERROR ] : ", e); Problem problem = Problem.builder() - .withStatus(INTERNAL_SERVER_ERROR) - .withTitle(INTERNAL_SERVER_ERROR.getReasonPhrase()) + .withStatus(Status.INTERNAL_SERVER_ERROR) + .withTitle(Status.INTERNAL_SERVER_ERROR.getReasonPhrase()) .withDetail(e.getMessage()) .build(); @@ -63,8 +61,8 @@ public ResponseEntity methodArgumentNotValidExceptionHandler(MethodArgu }); Problem problem = Problem.builder() - .withStatus(BAD_REQUEST) - .withTitle(BAD_REQUEST.getReasonPhrase()) + .withStatus(Status.BAD_REQUEST) + .withTitle(Status.BAD_REQUEST.getReasonPhrase()) .with("parameters", responses) .build(); @@ -88,8 +86,8 @@ public Problem constraintViolationExceptionHandler(ConstraintViolationException }); return Problem.builder() - .withStatus(BAD_REQUEST) - .withTitle(BAD_REQUEST.getReasonPhrase()) + .withStatus(Status.BAD_REQUEST) + .withTitle(Status.BAD_REQUEST.getReasonPhrase()) .with("parameters", responses) .build(); } From bb0e15c43efb6ad33c0e2b31d9c890be7657d51c Mon Sep 17 00:00:00 2001 From: zinzoddari Date: Fri, 5 Jan 2024 01:10:49 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20foreach=EB=AC=B8=20map=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/RootExceptionHandler.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java index c84abd1..457afb0 100644 --- a/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java +++ b/src/main/java/org/idiot/yesslave/global/exception/RootExceptionHandler.java @@ -17,7 +17,6 @@ import org.zalando.problem.Status; import javax.validation.ConstraintViolationException; -import java.util.ArrayList; import java.util.List; @Slf4j @@ -54,11 +53,11 @@ public ResponseEntity methodArgumentNotValidExceptionHandler(MethodArgu BindingResult bindingResult = e.getBindingResult(); - List responses = new ArrayList<>(); - - bindingResult.getFieldErrors().forEach(fieldError -> { - responses.add(new InvalidResponse(fieldError.getField(), fieldError.getDefaultMessage(), fieldError.getRejectedValue())); - }); + List responses = bindingResult.getFieldErrors().stream() + .map(fieldError -> new InvalidResponse(fieldError.getField() + , fieldError.getDefaultMessage() + , fieldError.getRejectedValue()) + ).toList(); Problem problem = Problem.builder() .withStatus(Status.BAD_REQUEST) @@ -79,11 +78,11 @@ public ResponseEntity methodArgumentNotValidExceptionHandler(MethodArgu public Problem constraintViolationExceptionHandler(ConstraintViolationException e) { log.error("[ 400 ERROR ] : ", e); - List responses = new ArrayList<>(); - - e.getConstraintViolations().forEach(fieldError -> { - responses.add(new InvalidResponse(fieldError.getPropertyPath().toString(), fieldError.getMessage(), fieldError.getInvalidValue())); - }); + List responses = e.getConstraintViolations().stream() + .map(fieldError -> new InvalidResponse(fieldError.getPropertyPath().toString() + , fieldError.getMessage() + , fieldError.getInvalidValue()) + ).toList(); return Problem.builder() .withStatus(Status.BAD_REQUEST)