Skip to content

Commit

Permalink
Merge pull request #32 from f-lab-edu/feature/31
Browse files Browse the repository at this point in the history
feat: 전역 예외 처리
  • Loading branch information
dani820 authored Oct 7, 2024
2 parents e083b2e + a76074d commit 817595b
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.inmybook.application.port.out.ReadPostPort;
import com.inmybook.application.port.out.RegisterPostPort;
import com.inmybook.domain.post.Post;
import com.inmybook.error.ErrorCode;
import com.inmybook.error.exception.PostNotFoundException;

@Repository
public class InMemoryPostRepository implements RegisterPostPort, ReadPostPort {
Expand All @@ -27,6 +29,6 @@ public Post findPostById(String id) {
return post;
}
}
throw new RuntimeException("독서록 정보를 찾을 수 없습니다.");
throw new PostNotFoundException(ErrorCode.POST_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.inmybook.application.service.exception;

import com.inmybook.error.ErrorCode;
import com.inmybook.error.exception.InMyBookException;

import lombok.Getter;

@Getter
public class PostDeletionFailedException extends InMyBookException {
public PostDeletionFailedException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.inmybook.application.service.exception;

import com.inmybook.error.ErrorCode;
import com.inmybook.error.exception.InMyBookException;

import lombok.Getter;

@Getter
public class PostModificationFailedException extends InMyBookException {
public PostModificationFailedException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.inmybook.application.service.exception;

import com.inmybook.error.ErrorCode;
import com.inmybook.error.exception.InMyBookException;

import lombok.Getter;

@Getter
public class PostRegistrationFailedException extends InMyBookException {
public PostRegistrationFailedException(ErrorCode errorCode) {
super(errorCode);
}
}
12 changes: 7 additions & 5 deletions src/main/java/com/inmybook/domain/post/PostFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@
import org.springframework.stereotype.Component;

import com.inmybook.application.port.in.RegisterPostCommand;
import com.inmybook.application.service.exception.PostRegistrationFailedException;
import com.inmybook.domain.member.Member;
import com.inmybook.error.ErrorCode;

@Component
public class PostFactory {
public Post createPost(RegisterPostCommand registerPostCommand) {
Thumbnail thumbnail = new Thumbnail();
if (registerPostCommand.thumbnailImg() != null) {
try {
thumbnail = new Thumbnail(registerPostCommand.thumbnailImg().getName()
, registerPostCommand.thumbnailImg().getContentType()
, registerPostCommand.thumbnailImg().getSize()
, registerPostCommand.thumbnailImg().getBytes());
thumbnail = new Thumbnail(registerPostCommand.thumbnailImg().getName(),
registerPostCommand.thumbnailImg().getContentType(),
registerPostCommand.thumbnailImg().getSize(),
registerPostCommand.thumbnailImg().getBytes());
} catch (IOException e) {
throw new RuntimeException("독서록 게시글을 등록할 수 없습니다.");
throw new PostRegistrationFailedException(ErrorCode.FILE_READ_ERROR);
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/inmybook/error/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.inmybook.error;

import org.springframework.http.HttpStatus;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum ErrorCode {
INVALID_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
INVALID_REQUIRED_PARAMETER(HttpStatus.BAD_REQUEST, "필수 파라미터가 존재하지 않습니다."),
UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "리소스에 접근하려면 인증이 필요합니다."),
FORBIDDEN_ACCESS(HttpStatus.FORBIDDEN, "접근 권한이 없습니다."),
NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 정보입니다."),
NOT_FOUND_HTTP_METHOD(HttpStatus.NOT_FOUND, "존재하지 않는 HTTP 메소드입니다."),
NOT_ALLOWED_HTTP_METHOD(HttpStatus.METHOD_NOT_ALLOWED, "허용되지 않는 HTTP 메소드입니다."),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 에러가 발생하였습니다. 다시 시도해주세요."),

POST_NOT_FOUND(HttpStatus.NOT_FOUND, "독서록 정보가 존재하지 않습니다."),
POST_REGISTRATION_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "독서록 등록 중 문제가 발생했습니다. 다시 시도해주세요."),
POST_MODIFICATION_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "독서록 수정 중 문제가 발생했습니다. 다시 시도해주세요."),
POST_DELETION_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "독서록 삭제 중 문제가 발생했습니다. 다시 시도해주세요."),

FILE_READ_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "파일 읽기 작업 중 문제가 발생했습니다. 다시 시도해주세요.");

private final HttpStatus httpStatus;
private final String message;
}
32 changes: 32 additions & 0 deletions src/main/java/com/inmybook/error/ErrorResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.inmybook.error;

import org.springframework.http.ResponseEntity;

import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@Builder
@RequiredArgsConstructor
public class ErrorResponseDto {
public final int httpStatus;
public final String code;
public final String message;

public ErrorResponseDto(ErrorCode errorCode) {
this.httpStatus = errorCode.getHttpStatus().value();
this.code = errorCode.name();
this.message = errorCode.getMessage();
}

public static ResponseEntity<ErrorResponseDto> error(ErrorCode errorCode) {
return ResponseEntity
.status(errorCode.getHttpStatus())
.body(ErrorResponseDto.builder()
.httpStatus(errorCode.getHttpStatus().value())
.code(errorCode.name())
.message(errorCode.getMessage())
.build());
}
}
87 changes: 87 additions & 0 deletions src/main/java/com/inmybook/error/GlobalExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.inmybook.error;

import java.nio.file.AccessDeniedException;

import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.inmybook.application.service.exception.PostDeletionFailedException;
import com.inmybook.application.service.exception.PostModificationFailedException;
import com.inmybook.application.service.exception.PostRegistrationFailedException;
import com.inmybook.error.exception.PostNotFoundException;
import com.inmybook.error.exception.UnauthorizedException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UnauthorizedException.class)
protected ResponseEntity<ErrorResponseDto> handleUnauthorizedException(
UnauthorizedException ex) {
log.error("handleUnauthorizedException", ex);
ErrorCode errorCode = ErrorCode.UNAUTHORIZED_ACCESS;
return ErrorResponseDto.error(errorCode);
}

@ExceptionHandler(AccessDeniedException.class)
protected ResponseEntity<ErrorResponseDto> handleAccessDeniedException(
AccessDeniedException ex) {
log.error("handleAccessDeniedException", ex);
ErrorCode errorCode = ErrorCode.FORBIDDEN_ACCESS;
return ErrorResponseDto.error(errorCode);
}

@ExceptionHandler(NoHandlerFoundException.class)
protected ResponseEntity<ErrorResponseDto> handleNoHandlerFoundException(
NoHandlerFoundException ex) {
log.error("handleNoHandlerFoundException", ex);
ErrorCode errorCode = ErrorCode.NOT_FOUND_HTTP_METHOD;
return ErrorResponseDto.error(errorCode);
}

@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
protected ResponseEntity<ErrorResponseDto> handleHttpRequestMethodNotSupportedException(
HttpRequestMethodNotSupportedException ex) {
log.error("handleHttpRequestMethodNotSupportedException", ex);
ErrorCode errorCode = ErrorCode.NOT_ALLOWED_HTTP_METHOD;
return ErrorResponseDto.error(errorCode);
}

@ExceptionHandler(PostModificationFailedException.class)
protected ResponseEntity<ErrorResponseDto> handlePostModificationFailedException(
PostModificationFailedException ex) {
log.error("handlePostModificationFailedException", ex);
return ErrorResponseDto.error(ex.getErrorCode());
}

@ExceptionHandler(PostNotFoundException.class)
protected ResponseEntity<ErrorResponseDto> handlePostNotFoundException(PostNotFoundException ex) {
log.error("handlePostNotFoundException", ex);
return ErrorResponseDto.error(ex.getErrorCode());
}

@ExceptionHandler(PostRegistrationFailedException.class)
protected ResponseEntity<ErrorResponseDto> handlePostRegistrationFailedException(
PostRegistrationFailedException ex) {
log.error("handlePostRegistrationFailedException", ex);
return ErrorResponseDto.error(ex.getErrorCode());
}

@ExceptionHandler(PostDeletionFailedException.class)
protected ResponseEntity<ErrorResponseDto> handlePostDeletionFailedException(PostDeletionFailedException ex) {
log.error("handlePostDeletionFailedException", ex);
return ErrorResponseDto.error(ex.getErrorCode());
}

@ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponseDto> handleAllException(Exception ex) {
log.error("handleAllException", ex);
ErrorCode errorCode = ErrorCode.INTERNAL_SERVER_ERROR;
return ErrorResponseDto.error(errorCode);
}

}
16 changes: 16 additions & 0 deletions src/main/java/com/inmybook/error/exception/InMyBookException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.inmybook.error.exception;

import com.inmybook.error.ErrorCode;

import lombok.Getter;

@Getter
public class InMyBookException extends RuntimeException {
// ErrorCode가 HttpStatus, message를 가짐으로써 에러 변경 범위 최소화
private final ErrorCode errorCode;

public InMyBookException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.inmybook.error.exception;

import com.inmybook.error.ErrorCode;

import lombok.Getter;

@Getter
public class PostNotFoundException extends InMyBookException {
public PostNotFoundException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.inmybook.error.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class UnauthorizedException extends RuntimeException {
public UnauthorizedException(String message) {
super(message);
}
}
5 changes: 4 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
spring:
application:
name: inmybook
web:
resources:
add-mappings: false
springdoc:
api-docs:
path: /api-docs
Expand All @@ -12,4 +15,4 @@ springdoc:
path: /swagger-ui.html
disable-swagger-default-url: true
display-query-params-without-oauth2: true
doc-expansion: none
doc-expansion: none

0 comments on commit 817595b

Please sign in to comment.