Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ControllerAdvice 개편 #950

Merged
merged 4 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -33,88 +34,79 @@
@Slf4j
@RestControllerAdvice
public class ControllerAdvice implements RequestRejectedHandler {
private static final String MESSAGE_FORMAT = "{} (traceId: {})";
private static final String MESSAGE_FORMAT = "%s (traceId: %s)";
private static final String TRACE_ID_KEY = "traceId";

@ExceptionHandler(NoSuchOAuthMemberException.class)
public ResponseEntity<OAuthLoginFailErrorResponse> oAuthLoginFailHandler(final NoSuchOAuthMemberException exception) {
logInfo(exception.getMessage());
logInfo(exception);
return ResponseEntity
.status(exception.getStatus())
.body(OAuthLoginFailErrorResponse.from(exception));
}

@ExceptionHandler(InputFieldException.class)
public ResponseEntity<InputFieldErrorResponse> inputFieldExceptionHandler(final InputFieldException exception) {
logInfo(exception.getMessage());
logInfo(exception);
return ResponseEntity
.status(exception.getStatus())
.body(InputFieldErrorResponse.from(exception));
}

@ExceptionHandler(InfrastructureMalfunctionException.class)
public ResponseEntity<ErrorResponse> wrongConfigurationOfInfrastructureException(final InfrastructureMalfunctionException exception) {
logWarn(exception.getMessage(), exception);
logWarn(exception);
return ResponseEntity
.status(exception.getStatus())
.body(ErrorResponse.from(exception));
}

@ExceptionHandler(ZzimkkongException.class)
public ResponseEntity<ErrorResponse> zzimkkongExceptionHandler(final ZzimkkongException exception) {
logInfo(exception.getMessage());
logInfo(exception);
return ResponseEntity
.status(exception.getStatus())
.body(ErrorResponse.from(exception));
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<InputFieldErrorResponse> invalidArgumentHandler(final MethodArgumentNotValidException exception) {
logInfo(exception.getMessage());
logInfo(exception);
return ResponseEntity.badRequest().body(InputFieldErrorResponse.from(exception));
}

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<ErrorResponse> invalidParamHandler(final ConstraintViolationException exception) {
logInfo(exception.getMessage());
logInfo(exception);
return ResponseEntity.badRequest().body(ErrorResponse.from(exception));
}

@ExceptionHandler({InvalidFormatException.class, HttpMessageNotReadableException.class})
public ResponseEntity<ErrorResponse> invalidFormatHandler() {
logInfo(FORMAT_MESSAGE);
@ExceptionHandler({InvalidFormatException.class, HttpMessageNotReadableException.class, MethodArgumentTypeMismatchException.class})
public ResponseEntity<ErrorResponse> invalidFormatHandler(final Exception exception) {
logInfo(exception);
return ResponseEntity.badRequest().body(ErrorResponse.invalidFormat());
}

@ExceptionHandler(DataAccessException.class)
public ResponseEntity<Void> invalidDataAccessHandler(final DataAccessException exception) {
logWarn(SERVER_ERROR_MESSAGE, exception);
return ResponseEntity.internalServerError().build();
public ResponseEntity<ErrorResponse> invalidDataAccessHandler(final DataAccessException exception) {
logWarn(exception);
return ResponseEntity.internalServerError().body(ErrorResponse.internalServerError());
}

@ExceptionHandler(Exception.class)
public ResponseEntity<Void> unhandledExceptionHandler(final Exception exception) {
logWarn(exception.getMessage(), exception);
return ResponseEntity.internalServerError().build();
public ResponseEntity<ErrorResponse> unhandledExceptionHandler(final Exception exception) {
logWarn(exception);
return ResponseEntity.internalServerError().body(ErrorResponse.internalServerError());
}

private void logInfo(String message) {
log.info(MESSAGE_FORMAT,
message,
value(TRACE_ID_KEY, getTraceId()));
private void logInfo(Exception exception) {
String logMessage = String.format(MESSAGE_FORMAT, exception.getMessage(), value(TRACE_ID_KEY, getTraceId()));
log.info(logMessage, exception);
}

private void logWarn(String message, Exception exception) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);

exception.printStackTrace(printWriter);
String stackTrace = stringWriter.toString();

log.warn(MESSAGE_FORMAT,
message,
value(TRACE_ID_KEY, getTraceId()),
value("stack_trace", stackTrace));
private void logWarn(Exception exception) {
String logMessage = String.format(MESSAGE_FORMAT, exception.getMessage(), value(TRACE_ID_KEY, getTraceId()));
log.warn(logMessage, exception);
}

private Object getTraceId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.validation.ConstraintViolationException;

import static com.woowacourse.zzimkkong.dto.ValidatorMessage.FORMAT_MESSAGE;
import static com.woowacourse.zzimkkong.dto.ValidatorMessage.SERVER_ERROR_MESSAGE;

@Getter
@NoArgsConstructor
Expand All @@ -28,4 +29,8 @@ public static ErrorResponse from(final ConstraintViolationException exception) {
public static ErrorResponse invalidFormat() {
return new ErrorResponse(FORMAT_MESSAGE);
}

public static ErrorResponse internalServerError() {
return new ErrorResponse(SERVER_ERROR_MESSAGE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private ValidatorMessage() {
public static final String NOTICE_MESSAGE = "공지사항은 100자 이내로 작성 가능합니다.";
public static final String FORMAT_MESSAGE = "날짜 및 시간 데이터 형식이 올바르지 않습니다.";
public static final String DAY_OF_WEEK_MESSAGE = "올바른 요일 형식이 아닙니다.";
public static final String SERVER_ERROR_MESSAGE = "예상치 못한 문제가 발생했습니다. 개발자에게 문의하세요.";
public static final String SERVER_ERROR_MESSAGE = "일시적으로 접속이 원활하지 않습니다. 잠시 후 다시 이용해 주시기 바랍니다.";
public static final String TIME_UNIT_MESSAGE = "시간 단위는 10, 30, 60, 120입니다.";
public static final String SETTING_COUNT_MESSAGE = "공간의 예약 조건이 최소 1개는 존재해야 합니다.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.http.HttpStatus;

public class TokenExpiredException extends ZzimkkongException {
private static final String MESSAGE = "로그인이 필요한 서비스입니다.";
private static final String MESSAGE = "로그인 인증 유효기간이 만료되었습니다. 다시 로그인 해주세요.";

public TokenExpiredException() {
super(MESSAGE, HttpStatus.UNAUTHORIZED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ public void validateToken(String token) {
}

public String getPayload(String token) {
return jwtParser.parseClaimsJws(token).getBody().getSubject();
try {
return jwtParser.parseClaimsJws(token).getBody().getSubject();
} catch (ExpiredJwtException e) {
throw new TokenExpiredException();
} catch (JwtException e) {
throw new InvalidTokenException();
}
}

public static PayloadBuilder payloadBuilder() {
Expand Down