Skip to content

Commit

Permalink
♻️ Refactor : 에러핸들러 대규모 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
CYY1007 committed Oct 5, 2023
1 parent dba7627 commit 8ed21ce
Show file tree
Hide file tree
Showing 56 changed files with 768 additions and 478 deletions.
4 changes: 2 additions & 2 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
if %ERRORLEVEL% equ 0 goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return commonStatus instead of
rem the _cmd.exe /c_ return commonStatus!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
import feign.codec.ErrorDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import zipdabang.server.base.Code;
import zipdabang.server.base.exception.handler.CustomFeignClientException;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import zipdabang.server.apiPayload.code.CommonStatus;
import zipdabang.server.apiPayload.exception.handler.CustomFeignClientException;

public class FeignClientExceptionErrorDecoder implements ErrorDecoder {

Expand All @@ -19,10 +16,10 @@ public class FeignClientExceptionErrorDecoder implements ErrorDecoder {
public Exception decode(String methodKey, Response response) {
if (response.status() >= 400 && response.status() <= 499) {
logger.error("{}번 에러 발생 : {}", response.status(), response.reason());
return new CustomFeignClientException(Code.FEIGN_CLIENT_ERROR_400);
return new CustomFeignClientException(CommonStatus.FEIGN_CLIENT_ERROR_400);
} else {
logger.error("500번대 에러 발생 : {}", response.reason());
return new CustomFeignClientException(Code.FEIGN_CLIENT_ERROR_500);
return new CustomFeignClientException(CommonStatus.FEIGN_CLIENT_ERROR_500);
}
}
}
8 changes: 8 additions & 0 deletions src/main/java/zipdabang/server/apiPayload/code/BaseCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package zipdabang.server.apiPayload.code;

public interface BaseCode {

public Reason getReason();

public Reason getReasonHttpStatus();
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package zipdabang.server.base;
package zipdabang.server.apiPayload.code;


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import zipdabang.server.base.exception.GeneralException;

import java.util.Arrays;
import java.util.Optional;
import java.util.function.Predicate;

@Getter
@RequiredArgsConstructor
public enum Code {
@AllArgsConstructor
public enum CommonStatus implements BaseCode {
OK(HttpStatus.OK,2000, "Ok"),

OAUTH_LOGIN(HttpStatus.OK,2050, "로그인 입니다."),
Expand Down Expand Up @@ -131,39 +127,28 @@ public enum Code {
//INTERNAL_SERVER_ERROR
FEIGN_CLIENT_ERROR_500(HttpStatus.OK, 5001, "Inter server Error in feign client");



private final HttpStatus httpStatus;
private final Integer code;
private final String message;

public String getMessage(Throwable e) {
return this.getMessage(this.getMessage() + " - " + e.getMessage());
// 결과 예시 - "Validation error - Reason why it isn't valid"
@Override
public Reason getReason() {
return Reason.builder()
.message(message)
.code(code)
.isSuccess((code >= 2000 && code < 3000) ? true : false)
.build();
}

public String getMessage(String message) {
return Optional.ofNullable(message)
.filter(Predicate.not(String::isBlank))
.orElse(this.getMessage());
@Override
public Reason getReasonHttpStatus() {
return Reason.builder()
.message(message)
.code(code)
.isSuccess((code >= 2000 && code < 3000) ? true : false)
.httpStatus(httpStatus)
.build()
;
}

public static Code valueOf(HttpStatus httpStatus) {
if (httpStatus == null) {
throw new GeneralException("HttpStatus is null.");
}

return Arrays.stream(values())
.filter(errorCode -> errorCode.getHttpStatus() == httpStatus)
.findFirst()
.orElseGet(() -> {
if (httpStatus.is4xxClientError()) {
return Code.BAD_REQUEST;
} else if (httpStatus.is5xxServerError()) {
return Code.INTERNAL_ERROR;
} else {
return Code.OK;
}
});
}
}
21 changes: 21 additions & 0 deletions src/main/java/zipdabang/server/apiPayload/code/Reason.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package zipdabang.server.apiPayload.code;

import lombok.Builder;
import lombok.Getter;
import org.springframework.http.HttpStatus;

import java.util.HashMap;

@Getter
@Builder
public class Reason {

private HttpStatus httpStatus;

private final boolean isSuccess;
private final Integer code;
private final String message;
private final HashMap<String, String>result;

public boolean getIsSuccess(){return isSuccess;}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package zipdabang.server.apiPayload.exception;

import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.User;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import zipdabang.server.apiPayload.code.CommonStatus;
import zipdabang.server.apiPayload.code.Reason;
import zipdabang.server.apiPayload.exception.base.GeneralException;
import zipdabang.server.apiPayload.reponse.ResponseDto;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Slf4j
@RestControllerAdvice(annotations = {RestController.class})
public class ExceptionAdvice extends ResponseEntityExceptionHandler {


@org.springframework.web.bind.annotation.ExceptionHandler
public ResponseEntity<Object> validation(ConstraintViolationException e, WebRequest request) {
String errorMessage = e.getConstraintViolations().stream()
.map(constraintViolation -> constraintViolation.getMessage())
.findFirst()
.orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생"));

return handleExceptionInternalConstraint(e, CommonStatus.valueOf(errorMessage),HttpHeaders.EMPTY,request);
}

@NotNull
@Override
public ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) {

Map<String, String> errors = new LinkedHashMap<>();

e.getBindingResult().getFieldErrors().stream()
.forEach(fieldError -> {
String fieldName = fieldError.getField();
String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse("");
errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage);
});

return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,CommonStatus.valueOf("BAD_REQUEST"),request,errors);
}

@org.springframework.web.bind.annotation.ExceptionHandler
public ResponseEntity<Object> exception(Exception e, WebRequest request) {
e.printStackTrace();

return handleExceptionInternalFalse(e, CommonStatus.INTERNAL_ERROR, HttpHeaders.EMPTY, CommonStatus.INTERNAL_ERROR.getHttpStatus(),request, e.getMessage());
}

@ExceptionHandler(value = GeneralException.class)
public ResponseEntity onThrowException(GeneralException generalException,
@AuthenticationPrincipal User user, HttpServletRequest request) {
getExceptionStackTrace(generalException, user, request);
Reason errorReasonHttpStatus = generalException.getErrorReasonHttpStatus();
return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request);
}

// protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Reason reason,
// HttpHeaders headers, HttpServletRequest request) {
// return handleExceptionInternal(ex, reason, headers, request);
// }


// private ResponseEntity<Object> handleExceptionInternal(Exception e, Reason errorReason,
// WebRequest request) {
// return handleExceptionInternal(e, errorReason, HttpHeaders.EMPTY, request);
// }

// private ResponseEntity<Object> handleExceptionInternal(Exception e, CommonStatus commonStatus,
// WebRequest request) {
// return handleExceptionInternal(e, Reason, HttpHeaders.EMPTY, request);
// }

private ResponseEntity<Object> handleExceptionInternal(Exception e, Reason reason,
HttpHeaders headers, HttpServletRequest request) {

ResponseDto<Object> body = ResponseDto.onFailure(reason.getCode(),reason.getMessage(),null);
// e.printStackTrace();

WebRequest webRequest = new ServletWebRequest(request);
return super.handleExceptionInternal(
e,
body,
headers,
reason.getHttpStatus(),
webRequest
);
}

private ResponseEntity<Object> handleExceptionInternalFalse(Exception e, CommonStatus errorCommonStatus,
HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) {
ResponseDto<Object> body = ResponseDto.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint);
return super.handleExceptionInternal(
e,
body,
headers,
status,
request
);
}

private ResponseEntity<Object> handleExceptionInternalArgs(Exception e, HttpHeaders headers, CommonStatus errorCommonStatus,
WebRequest request, Map<String, String> errorArgs) {
ResponseDto<Object> body = ResponseDto.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}

private ResponseEntity<Object> handleExceptionInternalConstraint(Exception e, CommonStatus errorCommonStatus,
HttpHeaders headers, WebRequest request) {
ResponseDto<Object> body = ResponseDto.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}

private void getExceptionStackTrace(Exception e, @AuthenticationPrincipal User user,
HttpServletRequest request) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);

pw.append("\n==========================!!!ERROR TRACE!!!==========================\n");
pw.append("uri: " + request.getRequestURI() + " " + request.getMethod() + "\n");
if (user != null) {
pw.append("uid: " + user.getUsername() + "\n");
}
pw.append(e.getMessage());
pw.append("\n=====================================================================");
log.error(sw.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package zipdabang.server.apiPayload.exception.base;

import lombok.AllArgsConstructor;
import lombok.Getter;
import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.code.Reason;

@Getter
@AllArgsConstructor
public class GeneralException extends RuntimeException {

private BaseCode code;

public Reason getErrorReason() {
return this.code.getReason();
}

public Reason getErrorReasonHttpStatus(){
return this.code.getReasonHttpStatus();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package zipdabang.server.apiPayload.exception.handler;

import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.exception.base.GeneralException;

public class AuthNumberException extends GeneralException {
public AuthNumberException(BaseCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package zipdabang.server.apiPayload.exception.handler;

import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.code.CommonStatus;
import zipdabang.server.apiPayload.exception.base.GeneralException;


public class CustomFeignClientException extends GeneralException {

public CustomFeignClientException(BaseCode errorCode){
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package zipdabang.server.apiPayload.exception.handler;

import org.springframework.security.core.AuthenticationException;
import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.code.CommonStatus;

public class JwtAuthenticationException extends AuthenticationException {

public JwtAuthenticationException(CommonStatus code){
super(code.name());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package zipdabang.server.apiPayload.exception.handler;


import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.code.CommonStatus;
import zipdabang.server.apiPayload.exception.base.GeneralException;

public class MemberException extends GeneralException {
public MemberException(BaseCode errorCommonStatus) {
super(errorCommonStatus);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package zipdabang.server.apiPayload.exception.handler;

import zipdabang.server.apiPayload.code.BaseCode;
import zipdabang.server.apiPayload.exception.base.GeneralException;


public class RecipeException extends GeneralException {
public RecipeException(BaseCode errorCommonStatus) {
super(errorCommonStatus);
}
}
Loading

0 comments on commit 8ed21ce

Please sign in to comment.