diff --git a/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java b/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java index b3423e102..4ed762229 100644 --- a/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java +++ b/backend/src/main/java/reviewme/global/GlobalExceptionHandler.java @@ -2,8 +2,7 @@ import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; @@ -24,52 +23,59 @@ import reviewme.global.exception.BadRequestException; import reviewme.global.exception.FieldErrorResponse; import reviewme.global.exception.NotFoundException; +import reviewme.global.exception.ReviewMeException; import reviewme.global.exception.UnAuthorizedException; +@Slf4j @RestControllerAdvice public class GlobalExceptionHandler { - private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); - @ExceptionHandler(NotFoundException.class) public ProblemDetail handleNotFoundException(NotFoundException ex) { + logReviewMeException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getErrorMessage()); } @ExceptionHandler(BadRequestException.class) public ProblemDetail handleBadRequestException(BadRequestException ex) { + logReviewMeException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getErrorMessage()); } @ExceptionHandler(UnAuthorizedException.class) public ProblemDetail handleUnAuthorizedException(UnAuthorizedException ex) { + logReviewMeException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, ex.getErrorMessage()); } @ExceptionHandler(Exception.class) public ProblemDetail handleException(Exception ex) { - log.error("An error occurred", ex); + logInitialServerError(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, "서버 에러가 발생했습니다."); } // Following exceptions are exceptions that occur in Spring @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ProblemDetail handleHttpRequestMethodNotSupportedException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.METHOD_NOT_ALLOWED, "지원하지 않는 HTTP 메서드입니다."); } @ExceptionHandler(HttpMediaTypeException.class) public ProblemDetail handleHttpMediaTypeException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "잘못된 media type 입니다."); } @ExceptionHandler({MissingRequestValueException.class, MissingServletRequestPartException.class}) public ProblemDetail handleMissingRequestException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "필수 요청 데이터가 누락되었습니다."); } @ExceptionHandler({ServletRequestBindingException.class, HttpMessageNotReadableException.class}) public ProblemDetail handleServletRequestBindingException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "요청을 읽을 수 없습니다."); } @@ -78,16 +84,19 @@ public ProblemDetail handleServletRequestBindingException(Exception ex) { TypeMismatchException.class, HandlerMethodValidationException.class }) public ProblemDetail handleRequestFormatException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "요청의 형식이 잘못되었습니다."); } @ExceptionHandler({NoHandlerFoundException.class, NoResourceFoundException.class}) public ProblemDetail handleNoHandlerFoundException(Exception ex) { + logSpringException(ex); return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, "잘못된 경로의 요청입니다."); } @ExceptionHandler(MethodArgumentNotValidException.class) public ProblemDetail handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { + logSpringException(ex); List fieldErrors = ex.getBindingResult() .getFieldErrors() .stream() @@ -104,4 +113,20 @@ public ProblemDetail handleMethodArgumentNotValid(MethodArgumentNotValidExceptio problemDetail.setProperties(properties); return problemDetail; } + + private void logReviewMeException(ReviewMeException ex) { + log.info("{} is occurred - {}", + ex.getClass().getSuperclass().getSimpleName(), + ex.getClass().getSimpleName(), + ex + ); + } + + private void logInitialServerError(Exception ex) { + log.error("Initial server error is occurred", ex); + } + + private void logSpringException(Exception ex) { + log.info("Spring error is occurred - {}: {}", ex.getClass().getSimpleName(), ex.getLocalizedMessage()); + } } diff --git a/backend/src/main/java/reviewme/keyword/domain/exception/DuplicateKeywordException.java b/backend/src/main/java/reviewme/keyword/domain/exception/DuplicateKeywordException.java index e765305b2..8823ece62 100644 --- a/backend/src/main/java/reviewme/keyword/domain/exception/DuplicateKeywordException.java +++ b/backend/src/main/java/reviewme/keyword/domain/exception/DuplicateKeywordException.java @@ -1,10 +1,14 @@ package reviewme.keyword.domain.exception; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class DuplicateKeywordException extends BadRequestException { - public DuplicateKeywordException() { + public DuplicateKeywordException(List selectedKeywordIds) { super("키워드는 중복되지 않게 선택해 주세요."); + log.info("Selected keywords are duplicated - selectedKeywordIds: {}", selectedKeywordIds); } } diff --git a/backend/src/main/java/reviewme/keyword/domain/exception/KeywordLimitExceedException.java b/backend/src/main/java/reviewme/keyword/domain/exception/KeywordLimitExceedException.java index 384621a4b..1ad30646d 100644 --- a/backend/src/main/java/reviewme/keyword/domain/exception/KeywordLimitExceedException.java +++ b/backend/src/main/java/reviewme/keyword/domain/exception/KeywordLimitExceedException.java @@ -1,10 +1,13 @@ package reviewme.keyword.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class KeywordLimitExceedException extends BadRequestException { public KeywordLimitExceedException(int minSize, int maxSize) { super("키워드는 최소 %d개, 최대 %d개 선택할 수 있어요.".formatted(minSize, maxSize)); + log.info("Selected keywords are out of bound - minSize:{}, maxSize: {}", minSize, maxSize); } } diff --git a/backend/src/main/java/reviewme/keyword/domain/exception/KeywordNotFoundException.java b/backend/src/main/java/reviewme/keyword/domain/exception/KeywordNotFoundException.java index ea438ef91..2b597cbf3 100644 --- a/backend/src/main/java/reviewme/keyword/domain/exception/KeywordNotFoundException.java +++ b/backend/src/main/java/reviewme/keyword/domain/exception/KeywordNotFoundException.java @@ -1,10 +1,13 @@ package reviewme.keyword.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.NotFoundException; +@Slf4j public class KeywordNotFoundException extends NotFoundException { - public KeywordNotFoundException() { + public KeywordNotFoundException(long id) { super("키워드가 존재하지 않아요."); + log.info("Keyword not found by id - id: {}", id); } } diff --git a/backend/src/main/java/reviewme/keyword/repository/KeywordRepository.java b/backend/src/main/java/reviewme/keyword/repository/KeywordRepository.java index 39613f267..aefb7a4df 100644 --- a/backend/src/main/java/reviewme/keyword/repository/KeywordRepository.java +++ b/backend/src/main/java/reviewme/keyword/repository/KeywordRepository.java @@ -9,6 +9,6 @@ public interface KeywordRepository extends JpaRepository { default Keyword getKeywordById(long id) { - return findById(id).orElseThrow(KeywordNotFoundException::new); + return findById(id).orElseThrow(() -> new KeywordNotFoundException(id)); } } diff --git a/backend/src/main/java/reviewme/question/domain/exception/DuplicateQuestionException.java b/backend/src/main/java/reviewme/question/domain/exception/DuplicateQuestionException.java index aba667354..0d853f635 100644 --- a/backend/src/main/java/reviewme/question/domain/exception/DuplicateQuestionException.java +++ b/backend/src/main/java/reviewme/question/domain/exception/DuplicateQuestionException.java @@ -1,10 +1,14 @@ package reviewme.question.domain.exception; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class DuplicateQuestionException extends BadRequestException { - public DuplicateQuestionException() { + public DuplicateQuestionException(List selectedQuestionIds) { super("질문은 중복될 수 없어요."); + log.info("Selected questions are duplicated - selectedQuestionIds: {}", selectedQuestionIds); } } diff --git a/backend/src/main/java/reviewme/question/domain/exception/QuestionNotFoundException.java b/backend/src/main/java/reviewme/question/domain/exception/QuestionNotFoundException.java index 42221d820..a5f2c3301 100644 --- a/backend/src/main/java/reviewme/question/domain/exception/QuestionNotFoundException.java +++ b/backend/src/main/java/reviewme/question/domain/exception/QuestionNotFoundException.java @@ -1,10 +1,13 @@ package reviewme.question.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.NotFoundException; +@Slf4j public class QuestionNotFoundException extends NotFoundException { - public QuestionNotFoundException() { + public QuestionNotFoundException(long questionId) { super("질문이 존재하지 않아요."); + log.info("Question not found - questionId: {}", questionId); } } diff --git a/backend/src/main/java/reviewme/review/domain/ReviewContent.java b/backend/src/main/java/reviewme/review/domain/ReviewContent.java index 3efa0a863..b4741de9c 100644 --- a/backend/src/main/java/reviewme/review/domain/ReviewContent.java +++ b/backend/src/main/java/reviewme/review/domain/ReviewContent.java @@ -38,7 +38,7 @@ public ReviewContent(long questionId, String answer) { private void validateAnswerLength(String answer) { if (answer.length() < MIN_ANSWER_LENGTH || answer.length() > MAX_ANSWER_LENGTH) { - throw new InvalidAnswerLengthException(MIN_ANSWER_LENGTH, MAX_ANSWER_LENGTH); + throw new InvalidAnswerLengthException(answer.length(), MIN_ANSWER_LENGTH, MAX_ANSWER_LENGTH); } } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/InvalidAnswerLengthException.java b/backend/src/main/java/reviewme/review/domain/exception/InvalidAnswerLengthException.java index a7a904774..abf6ffe60 100644 --- a/backend/src/main/java/reviewme/review/domain/exception/InvalidAnswerLengthException.java +++ b/backend/src/main/java/reviewme/review/domain/exception/InvalidAnswerLengthException.java @@ -1,10 +1,14 @@ package reviewme.review.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class InvalidAnswerLengthException extends BadRequestException { - public InvalidAnswerLengthException(int minLength, int maxLength) { + public InvalidAnswerLengthException(int answerLength, int minLength, int maxLength) { super("답변의 길이는 %d자 이상 %d자 이하여야 합니다.".formatted(minLength, maxLength)); + log.info("AnswerLength is out of bound - answerLength:{}, minLength: {}, maxLength: {}", + answerLength, minLength, maxLength); } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/InvalidProjectNameLengthException.java b/backend/src/main/java/reviewme/review/domain/exception/InvalidProjectNameLengthException.java index 7e5e21b02..d9637e654 100644 --- a/backend/src/main/java/reviewme/review/domain/exception/InvalidProjectNameLengthException.java +++ b/backend/src/main/java/reviewme/review/domain/exception/InvalidProjectNameLengthException.java @@ -1,10 +1,14 @@ package reviewme.review.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class InvalidProjectNameLengthException extends BadRequestException { - public InvalidProjectNameLengthException(int maxLength) { - super("프로젝트 이름은 1글자 이상 %d글자 이하여야 해요.".formatted(maxLength)); + public InvalidProjectNameLengthException(int projectNameLength, int minLength, int maxLength) { + super("프로젝트 이름은 %d글자 이상 %d글자 이하여야 해요.".formatted(minLength, maxLength)); + log.info("ProjectName is out of bound - projectNameLength:{}, minLength:{}, maxLength: {}", + projectNameLength, minLength, maxLength); } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/InvalidRevieweeNameLengthException.java b/backend/src/main/java/reviewme/review/domain/exception/InvalidRevieweeNameLengthException.java index 4454c5396..04aa70dba 100644 --- a/backend/src/main/java/reviewme/review/domain/exception/InvalidRevieweeNameLengthException.java +++ b/backend/src/main/java/reviewme/review/domain/exception/InvalidRevieweeNameLengthException.java @@ -1,10 +1,14 @@ package reviewme.review.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class InvalidRevieweeNameLengthException extends BadRequestException { - public InvalidRevieweeNameLengthException(int maxLength) { - super("리뷰이 이름은 1글자 이상 %d글자 이하여야 해요.".formatted(maxLength)); + public InvalidRevieweeNameLengthException(int revieweeNameLength, int minLength, int maxLength) { + super("리뷰이 이름은 %d글자 이상 %d글자 이하여야 해요.".formatted(minLength, maxLength)); + log.info("RevieweeName is out of bound - revieweeNameLength:{}, minLength:{}, maxLength: {}", + revieweeNameLength, minLength, maxLength); } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByGroupAccessCodeException.java b/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByGroupAccessCodeException.java new file mode 100644 index 000000000..345fbe3a1 --- /dev/null +++ b/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByGroupAccessCodeException.java @@ -0,0 +1,13 @@ +package reviewme.review.domain.exception; + +import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.NotFoundException; + +@Slf4j +public class ReviewGroupNotFoundByGroupAccessCodeException extends NotFoundException { + + public ReviewGroupNotFoundByGroupAccessCodeException(String groupAccessCode) { + super("리뷰 그룹을 찾을 수 없어요."); + log.info("ReviewGroup not found by groupAccessCode - groupAccessCode: {}", groupAccessCode); + } +} diff --git a/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByRequestReviewCodeException.java b/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByRequestReviewCodeException.java new file mode 100644 index 000000000..65f4c49b0 --- /dev/null +++ b/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundByRequestReviewCodeException.java @@ -0,0 +1,13 @@ +package reviewme.review.domain.exception; + +import lombok.extern.slf4j.Slf4j; +import reviewme.global.exception.NotFoundException; + +@Slf4j +public class ReviewGroupNotFoundByRequestReviewCodeException extends NotFoundException { + + public ReviewGroupNotFoundByRequestReviewCodeException(String requestReviewCode) { + super("리뷰 요청 코드에 대한 리뷰 그룹을 찾을 수 없어요."); + log.info("ReviewGroup not found by requestReviewCode - requestReviewCode: {}", requestReviewCode); + } +} diff --git a/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundException.java b/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundException.java deleted file mode 100644 index e9aef5620..000000000 --- a/backend/src/main/java/reviewme/review/domain/exception/ReviewGroupNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package reviewme.review.domain.exception; - -import reviewme.global.exception.NotFoundException; - -public class ReviewGroupNotFoundException extends NotFoundException { - - public ReviewGroupNotFoundException() { - super("리뷰 그룹을 찾을 수 없어요."); - } -} diff --git a/backend/src/main/java/reviewme/review/domain/exception/ReviewIsNotInReviewGroupException.java b/backend/src/main/java/reviewme/review/domain/exception/ReviewIsNotInReviewGroupException.java index 020f40ea9..72442d522 100644 --- a/backend/src/main/java/reviewme/review/domain/exception/ReviewIsNotInReviewGroupException.java +++ b/backend/src/main/java/reviewme/review/domain/exception/ReviewIsNotInReviewGroupException.java @@ -1,10 +1,13 @@ package reviewme.review.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.BadRequestException; +@Slf4j public class ReviewIsNotInReviewGroupException extends BadRequestException { - public ReviewIsNotInReviewGroupException() { + public ReviewIsNotInReviewGroupException(long reviewId, long reviewGroupId) { super("리뷰 그룹에 해당하는 리뷰가 아니에요."); + log.info("Review is not in review group - reviewId: {}, reviewGroupId: {}", reviewId, reviewGroupId); } } diff --git a/backend/src/main/java/reviewme/review/domain/exception/ReviewNotFoundException.java b/backend/src/main/java/reviewme/review/domain/exception/ReviewNotFoundException.java index 44e72cb01..27e05de2c 100644 --- a/backend/src/main/java/reviewme/review/domain/exception/ReviewNotFoundException.java +++ b/backend/src/main/java/reviewme/review/domain/exception/ReviewNotFoundException.java @@ -1,10 +1,13 @@ package reviewme.review.domain.exception; +import lombok.extern.slf4j.Slf4j; import reviewme.global.exception.NotFoundException; +@Slf4j public class ReviewNotFoundException extends NotFoundException { - public ReviewNotFoundException() { + public ReviewNotFoundException(long id) { super("리뷰가 존재하지 않아요."); + log.info("ReviewNotFoundException is occurred - id: {}", id); } } diff --git a/backend/src/main/java/reviewme/review/repository/QuestionRepository.java b/backend/src/main/java/reviewme/review/repository/QuestionRepository.java index 47346900e..829ea0dc5 100644 --- a/backend/src/main/java/reviewme/review/repository/QuestionRepository.java +++ b/backend/src/main/java/reviewme/review/repository/QuestionRepository.java @@ -9,6 +9,6 @@ public interface QuestionRepository extends JpaRepository { default Question getQuestionById(long id) { - return findById(id).orElseThrow(QuestionNotFoundException::new); + return findById(id).orElseThrow(() -> new QuestionNotFoundException(id)); } } diff --git a/backend/src/main/java/reviewme/review/repository/ReviewRepository.java b/backend/src/main/java/reviewme/review/repository/ReviewRepository.java index 010cf3261..0f048bc44 100644 --- a/backend/src/main/java/reviewme/review/repository/ReviewRepository.java +++ b/backend/src/main/java/reviewme/review/repository/ReviewRepository.java @@ -17,6 +17,6 @@ public interface ReviewRepository extends JpaRepository { Optional findByIdAndReviewGroupId(long reviewId, long reviewGroupId); default Review getReviewById(Long id) { - return findById(id).orElseThrow(ReviewNotFoundException::new); + return findById(id).orElseThrow(() -> new ReviewNotFoundException(id)); } } diff --git a/backend/src/main/java/reviewme/review/service/ReviewCreationKeywordValidator.java b/backend/src/main/java/reviewme/review/service/ReviewCreationKeywordValidator.java index 4cf96396b..a6ad1e497 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewCreationKeywordValidator.java +++ b/backend/src/main/java/reviewme/review/service/ReviewCreationKeywordValidator.java @@ -5,8 +5,6 @@ import org.springframework.stereotype.Component; import reviewme.keyword.domain.exception.DuplicateKeywordException; import reviewme.keyword.domain.exception.KeywordLimitExceedException; -import reviewme.keyword.domain.exception.KeywordNotFoundException; -import reviewme.keyword.repository.KeywordRepository; @Component @RequiredArgsConstructor @@ -15,12 +13,9 @@ public class ReviewCreationKeywordValidator { private static final int MIN_KEYWORD_COUNT = 1; private static final int MAX_KEYWORD_COUNT = 5; - private final KeywordRepository keywordRepository; - void validate(List selectedKeywordIds) { validateKeywordCount(selectedKeywordIds.size()); validateUniqueKeyword(selectedKeywordIds); - validateExistsKeyword(selectedKeywordIds); } private void validateUniqueKeyword(List selectedKeywordIds) { @@ -29,15 +24,7 @@ private void validateUniqueKeyword(List selectedKeywordIds) { .distinct() .count(); if (keywordsCount != distinctCount) { - throw new DuplicateKeywordException(); - } - } - - private void validateExistsKeyword(List selectedKeywordIds) { - boolean doesKeywordExist = selectedKeywordIds.stream() - .anyMatch(keywordRepository::existsById); - if (!doesKeywordExist) { - throw new KeywordNotFoundException(); + throw new DuplicateKeywordException(selectedKeywordIds); } } diff --git a/backend/src/main/java/reviewme/review/service/ReviewCreationQuestionValidator.java b/backend/src/main/java/reviewme/review/service/ReviewCreationQuestionValidator.java index f0e904548..a284f0356 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewCreationQuestionValidator.java +++ b/backend/src/main/java/reviewme/review/service/ReviewCreationQuestionValidator.java @@ -4,18 +4,13 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import reviewme.question.domain.exception.DuplicateQuestionException; -import reviewme.question.domain.exception.QuestionNotFoundException; -import reviewme.review.repository.QuestionRepository; @Component @RequiredArgsConstructor public class ReviewCreationQuestionValidator { - private final QuestionRepository questionRepository; - void validate(List questionIds) { validateUniqueQuestion(questionIds); - validateExistsQuestion(questionIds); } private void validateUniqueQuestion(List questionIds) { @@ -24,15 +19,7 @@ private void validateUniqueQuestion(List questionIds) { .distinct() .count(); if (questionsCount != distinctCount) { - throw new DuplicateQuestionException(); - } - } - - private void validateExistsQuestion(List questionIds) { - boolean doesQuestionExist = questionIds.stream() - .anyMatch(questionRepository::existsById); - if (!doesQuestionExist) { - throw new QuestionNotFoundException(); + throw new DuplicateQuestionException(questionIds); } } } diff --git a/backend/src/main/java/reviewme/review/service/ReviewService.java b/backend/src/main/java/reviewme/review/service/ReviewService.java index dcfa2fb30..a848017e9 100644 --- a/backend/src/main/java/reviewme/review/service/ReviewService.java +++ b/backend/src/main/java/reviewme/review/service/ReviewService.java @@ -10,7 +10,8 @@ import reviewme.review.domain.Review; import reviewme.review.domain.ReviewContent; import reviewme.review.domain.ReviewKeyword; -import reviewme.review.domain.exception.ReviewGroupNotFoundException; +import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException; +import reviewme.review.domain.exception.ReviewGroupNotFoundByRequestReviewCodeException; import reviewme.review.domain.exception.ReviewIsNotInReviewGroupException; import reviewme.review.dto.request.CreateReviewContentRequest; import reviewme.review.dto.request.CreateReviewRequest; @@ -52,7 +53,7 @@ public Long createReview(CreateReviewRequest request) { private Review saveReview(CreateReviewRequest request) { ReviewGroup reviewGroup = reviewGroupRepository.findByReviewRequestCode(request.reviewRequestCode()) - .orElseThrow(ReviewGroupNotFoundException::new); + .orElseThrow(() -> new ReviewGroupNotFoundByRequestReviewCodeException(request.reviewRequestCode())); List questionIds = request.reviewContents() .stream() @@ -80,7 +81,7 @@ private void saveReviewKeywords(List selectedKeywordIds, long savedReviewI @Transactional(readOnly = true) public ReviewSetupResponse findReviewCreationSetup(String reviewRequestCode) { ReviewGroup reviewGroup = reviewGroupRepository.findByReviewRequestCode(reviewRequestCode) - .orElseThrow(ReviewGroupNotFoundException::new); + .orElseThrow(() -> new ReviewGroupNotFoundByRequestReviewCodeException(reviewRequestCode)); return createReviewSetupResponse(reviewGroup); } @@ -103,10 +104,10 @@ private ReviewSetupResponse createReviewSetupResponse(ReviewGroup reviewGroup) { @Transactional(readOnly = true) public ReviewDetailResponse findReceivedReviewDetail(String groupAccessCode, long reviewId) { ReviewGroup reviewGroup = reviewGroupRepository.findByGroupAccessCode(groupAccessCode) - .orElseThrow(ReviewGroupNotFoundException::new); + .orElseThrow(() -> new ReviewGroupNotFoundByGroupAccessCodeException(groupAccessCode)); Review review = reviewRepository.findByIdAndReviewGroupId(reviewId, reviewGroup.getId()) - .orElseThrow(ReviewIsNotInReviewGroupException::new); + .orElseThrow(() -> new ReviewIsNotInReviewGroupException(reviewId, reviewGroup.getId())); return createReviewDetailResponse(review, reviewGroup); } @@ -140,7 +141,7 @@ private ReviewDetailResponse createReviewDetailResponse(Review review, ReviewGro @Transactional(readOnly = true) public ReceivedReviewsResponse findReceivedReviews(String groupAccessCode) { ReviewGroup reviewGroup = reviewGroupRepository.findByGroupAccessCode(groupAccessCode) - .orElseThrow(ReviewGroupNotFoundException::new); + .orElseThrow(() -> new ReviewGroupNotFoundByGroupAccessCodeException(groupAccessCode)); List reviewResponses = reviewRepository.findReceivedReviewsByGroupId(reviewGroup.getId()) .stream() diff --git a/backend/src/main/java/reviewme/reviewgroup/domain/ReviewGroup.java b/backend/src/main/java/reviewme/reviewgroup/domain/ReviewGroup.java index 2170fc8f4..01c55401e 100644 --- a/backend/src/main/java/reviewme/reviewgroup/domain/ReviewGroup.java +++ b/backend/src/main/java/reviewme/reviewgroup/domain/ReviewGroup.java @@ -18,7 +18,9 @@ @Getter public class ReviewGroup { + private static final int MIN_REVIEWEE_LENGTH = 1; private static final int MAX_REVIEWEE_LENGTH = 50; + private static final int MIN_PROJECT_NAME_LENGTH = 1; private static final int MAX_PROJECT_NAME_LENGTH = 50; @Id @@ -47,14 +49,16 @@ public ReviewGroup(String reviewee, String projectName, String reviewRequestCode } private void validateRevieweeLength(String reviewee) { - if (reviewee.isBlank() || reviewee.length() > MAX_REVIEWEE_LENGTH) { - throw new InvalidRevieweeNameLengthException(MAX_REVIEWEE_LENGTH); + if (reviewee.length() < MIN_REVIEWEE_LENGTH || reviewee.length() > MAX_REVIEWEE_LENGTH) { + throw new InvalidRevieweeNameLengthException(reviewee.length(), MIN_REVIEWEE_LENGTH, MAX_REVIEWEE_LENGTH); } } private void validateProjectNameLength(String projectName) { - if (projectName.isBlank() || projectName.length() > MAX_PROJECT_NAME_LENGTH) { - throw new InvalidProjectNameLengthException(MAX_PROJECT_NAME_LENGTH); + if (projectName.length() < MIN_PROJECT_NAME_LENGTH || projectName.length() > MAX_PROJECT_NAME_LENGTH) { + throw new InvalidProjectNameLengthException( + projectName.length(), MIN_PROJECT_NAME_LENGTH, MAX_PROJECT_NAME_LENGTH + ); } } } diff --git a/backend/src/main/resources/logback-spring.xml b/backend/src/main/resources/logback-spring.xml index 507469ab2..3b744db47 100644 --- a/backend/src/main/resources/logback-spring.xml +++ b/backend/src/main/resources/logback-spring.xml @@ -6,12 +6,14 @@ + UTF-8 ${CONSOLE_LOG_PATTERN} + UTF-8 ${FILE_LOG_PATTERN} utf8 diff --git a/backend/src/test/java/reviewme/review/service/ReviewCreationKeywordValidatorTest.java b/backend/src/test/java/reviewme/review/service/ReviewCreationKeywordValidatorTest.java index b295a413d..1f7897e06 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewCreationKeywordValidatorTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewCreationKeywordValidatorTest.java @@ -13,7 +13,6 @@ import reviewme.keyword.domain.Keyword; import reviewme.keyword.domain.exception.DuplicateKeywordException; import reviewme.keyword.domain.exception.KeywordLimitExceedException; -import reviewme.keyword.domain.exception.KeywordNotFoundException; import reviewme.keyword.repository.KeywordRepository; import reviewme.support.ServiceTest; @@ -26,23 +25,6 @@ class ReviewCreationKeywordValidatorTest { @Autowired KeywordRepository keywordRepository; - @Test - void 존재하는_키워드의_아이디인지_검사한다() { - // given - Keyword keyword1 = keywordRepository.save(회의를_이끌어요.create()); - Keyword keyword2 = keywordRepository.save(추진력이_좋아요.create()); - long nonExistKeywordId = Long.MAX_VALUE; - - // when, then - assertAll( - () -> assertThatCode( - () -> reviewCreationKeywordValidator.validate(List.of(keyword1.getId(), keyword2.getId()))) - .doesNotThrowAnyException(), - () -> assertThatCode(() -> reviewCreationKeywordValidator.validate(List.of(nonExistKeywordId))) - .isInstanceOf(KeywordNotFoundException.class) - ); - } - @Test void 중복되는_아이디의_키워드인지_검사한다() { // given diff --git a/backend/src/test/java/reviewme/review/service/ReviewCreationQuestionValidatorTest.java b/backend/src/test/java/reviewme/review/service/ReviewCreationQuestionValidatorTest.java index b21b1fbe9..a5e79ba69 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewCreationQuestionValidatorTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewCreationQuestionValidatorTest.java @@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import reviewme.question.domain.exception.DuplicateQuestionException; -import reviewme.question.domain.exception.QuestionNotFoundException; import reviewme.review.repository.QuestionRepository; import reviewme.support.ServiceTest; @@ -22,21 +21,6 @@ class ReviewCreationQuestionValidatorTest { @Autowired private QuestionRepository questionRepository; - @Test - void 존재하는_질문의_아이디인지_검사한다() { - // given - long existQuestionId = questionRepository.save(소프트스킬이_어떤가요.create()).getId(); - long nonExistQuestionId = Long.MAX_VALUE; - - // when, then - assertAll( - () -> assertThatCode(() -> reviewCreationQuestionValidator.validate(List.of(existQuestionId))) - .doesNotThrowAnyException(), - () -> assertThatCode(() -> reviewCreationQuestionValidator.validate(List.of(nonExistQuestionId))) - .isInstanceOf(QuestionNotFoundException.class) - ); - } - @Test void 중복되는_아이디의_질문인지_검사한다() { // given diff --git a/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java b/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java index be62e6f80..b009cb1ee 100644 --- a/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java +++ b/backend/src/test/java/reviewme/review/service/ReviewServiceTest.java @@ -20,7 +20,7 @@ import reviewme.review.domain.Review; import reviewme.review.domain.ReviewContent; import reviewme.review.domain.ReviewKeyword; -import reviewme.review.domain.exception.ReviewGroupNotFoundException; +import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException; import reviewme.review.domain.exception.ReviewIsNotInReviewGroupException; import reviewme.review.dto.request.CreateReviewContentRequest; import reviewme.review.dto.request.CreateReviewRequest; @@ -118,7 +118,7 @@ class ReviewServiceTest { @Test void 확인_코드에_해당하는_그룹이_없는_경우_예외가_발생한다() { assertThatThrownBy(() -> reviewService.findReceivedReviews("abc")) - .isInstanceOf(ReviewGroupNotFoundException.class); + .isInstanceOf(ReviewGroupNotFoundByGroupAccessCodeException.class); } @Test @@ -176,7 +176,7 @@ class ReviewServiceTest { // when, then assertThatThrownBy(() -> reviewService.findReceivedReviewDetail("wrongGroupAccessCode", review.getId())) - .isInstanceOf(ReviewGroupNotFoundException.class); + .isInstanceOf(ReviewGroupNotFoundByGroupAccessCodeException.class); } @Test