예외 정의, 모니터링을 위한 시스템 구축작업

This commit is contained in:
jinia91
2022-04-21 23:08:52 +09:00
parent 95d995694e
commit fffd4c60a3
23 changed files with 211 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ import myblog.blog.article.application.port.incomming.TempArticleUseCase;
import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase;
import myblog.blog.article.application.port.incomming.TagsQueriesUseCase;
import myblog.blog.category.appliacation.port.incomming.CategoryQueriesUseCase;
import myblog.blog.category.domain.CategoryNotFoundException;
import myblog.blog.shared.application.port.incomming.LayoutRenderingUseCase;
import myblog.blog.article.application.port.incomming.request.ArticleCreateCommand;
@@ -110,7 +111,7 @@ public class ArticleController {
if (categoryCntSub.getTitle().equals(category)) return categoryCntSub.getCount();
}
}
throw new IllegalArgumentException("'"+category+"' 라는 카테고리는 존재하지 않습니다.");
throw new CategoryNotFoundException();
}
/*
- 태그별 게시물 조회하기

View File

@@ -0,0 +1,6 @@
package myblog.blog.article.adapter.outgoing.model;
import myblog.blog.shared.domain.ExternalErrorException;
public class GithubExternalErrorException extends ExternalErrorException {
}

View File

@@ -1,6 +1,8 @@
package myblog.blog.article.adapter.outgoing.persistence;
import myblog.blog.article.adapter.outgoing.model.GithubExternalErrorException;
import myblog.blog.article.domain.Article;
import myblog.blog.shared.domain.ExternalErrorException;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;
@@ -29,6 +31,7 @@ public class GithubRepoArticleRepository {
.commit();
} catch (IOException e) {
e.printStackTrace();
throw new GithubExternalErrorException();
}
}

View File

@@ -3,6 +3,7 @@ package myblog.blog.article.application;
import lombok.RequiredArgsConstructor;
import myblog.blog.article.domain.Article;
import myblog.blog.article.domain.ArticleNotFoundException;
import myblog.blog.category.domain.Category;
import myblog.blog.article.application.port.incomming.response.ArticleResponseForCardBox;
@@ -82,7 +83,7 @@ public class ArticleQueries implements ArticleQueriesUseCase {
articles = articleRepositoryPort
.findBySubCategoryOrderByIdDesc(page, 5, category);
}
if(articles == null) throw new IllegalArgumentException("NotFoundArticleException");
if(articles == null) throw new ArticleNotFoundException();
return articles.stream().map(article -> MapperUtils.getModelMapper().map(article, ArticleResponseForCardBox.class)).collect(Collectors.toList());
}

View File

@@ -6,6 +6,7 @@ import myblog.blog.article.application.port.incomming.request.ArticleCreateComma
import myblog.blog.article.application.port.incomming.request.ArticleEditCommand;
import myblog.blog.article.application.port.incomming.ArticleUseCase;
import myblog.blog.article.application.port.incomming.TagUseCase;
import myblog.blog.article.domain.ArticleNotFoundException;
import myblog.blog.category.appliacation.port.incomming.CategoryUseCase;
import myblog.blog.member.application.port.incomming.MemberQueriesUseCase;
import myblog.blog.article.application.port.outgoing.ArticleBackupRepositoryPort;
@@ -53,7 +54,7 @@ public class ArticleService implements ArticleUseCase {
@CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true)
public void editArticle(ArticleEditCommand articleEditCommand) {
var article = articleRepositoryPort.findById(articleEditCommand.getArticleId())
.orElseThrow(() -> new IllegalArgumentException("NotFoundArticleException"));
.orElseThrow(ArticleNotFoundException::new);
var category = categoryUseCase.findCategory(articleEditCommand.getCategoryName());
tagUseCase.deleteAllTagsWith(article);
tagUseCase.createNewTagsAndArticleTagList(articleEditCommand.getTags(), article);

View File

@@ -0,0 +1,6 @@
package myblog.blog.article.domain;
import myblog.blog.shared.domain.ResourceNotFoundException;
public class ArticleNotFoundException extends ResourceNotFoundException {
}

View File

@@ -7,6 +7,7 @@ import myblog.blog.category.appliacation.port.incomming.CategoryUseCase;
import myblog.blog.category.appliacation.port.outgoing.CategoryRepositoryPort;
import myblog.blog.category.appliacation.port.incomming.response.CategorySimpleDto;
import myblog.blog.category.domain.CategoryNotFoundException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -25,7 +26,7 @@ public class CategoryService implements CategoryUseCase {
@Override
public Category findCategory(String title) {
return categoryRepositoryPort.findByTitle(title)
.orElseThrow(() -> new IllegalArgumentException("NotFoundCategoryException"));
.orElseThrow(CategoryNotFoundException::new);
}
/*
@@ -101,7 +102,7 @@ public class CategoryService implements CategoryUseCase {
Category parentCategory = null;
if (parent != null) {
parentCategory = categoryRepositoryPort.findByTitle(parent)
.orElseThrow(() -> new IllegalArgumentException("NotFoundCategoryException"));
.orElseThrow(CategoryNotFoundException::new);
}
Category category = Category.builder()

View File

@@ -0,0 +1,6 @@
package myblog.blog.category.domain;
import myblog.blog.shared.domain.ResourceNotFoundException;
public class CategoryNotFoundException extends ResourceNotFoundException {
}

View File

@@ -0,0 +1,10 @@
package myblog.blog.comment.adapter.incomming;
import myblog.blog.shared.domain.BadRequestException;
/*
- REST 컨트롤러 상태 메세지 전송용 커스텀 에러
*/
public class CommentBadRequestException extends BadRequestException {
}

View File

@@ -38,7 +38,7 @@ public class CommentController {
@Validated @RequestBody CommentForm commentForm, Errors errors,
@AuthenticationPrincipal PrincipalDetails principal){
if (errors.hasErrors()) {
throw new InvalidCommentRequestException(Objects.requireNonNull(errors.getFieldError()).getDefaultMessage());
throw new CommentBadRequestException();
}
MemberVo member = principal.getMember();

View File

@@ -1,9 +0,0 @@
package myblog.blog.comment.adapter.incomming;
/*
- REST 컨트롤러 상태 메세지 전송용 커스텀 에러
*/
public class InvalidCommentRequestException extends RuntimeException {
public InvalidCommentRequestException(String message) {
super(message);
}
}

View File

@@ -3,6 +3,7 @@ package myblog.blog.comment.domain;
import lombok.Builder;
import lombok.Getter;
import myblog.blog.article.domain.Article;
import myblog.blog.comment.adapter.incomming.CommentBadRequestException;
import myblog.blog.shared.domain.BasicEntity;
import myblog.blog.member.doamin.Member;
import org.hibernate.annotations.OnDelete;
@@ -73,7 +74,7 @@ public class Comment extends BasicEntity {
*/
private String removeDuplicatedEnter(String content) {
if(content == null || content.isEmpty()){
throw new IllegalArgumentException("InvalidContentException");
throw new CommentBadRequestException ();
}
char[] contentBox = new char[content.length()];
int idx = 0;

View File

@@ -1,6 +1,6 @@
package myblog.blog.infra.exception;
import myblog.blog.comment.adapter.incomming.InvalidCommentRequestException;
import myblog.blog.comment.adapter.incomming.CommentBadRequestException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
*/
@RestControllerAdvice
public class ExceptionRestControllerAdvice {
@ExceptionHandler(InvalidCommentRequestException.class)
@ExceptionHandler(CommentBadRequestException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleCategoryControllerException(RuntimeException e) {
return e.getMessage();

View File

@@ -6,6 +6,7 @@ import myblog.blog.member.application.port.outgoing.MemberRepositoryPort;
import myblog.blog.member.doamin.Member;
import myblog.blog.member.doamin.NotFoundMemberException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -17,6 +18,6 @@ public class MemberQueries implements MemberQueriesUseCase {
@Override
public Member findById(Long memberId) {
return memberRepositoryPort.findById(memberId)
.orElseThrow(() -> new IllegalArgumentException("NotFoundMemberException"));
.orElseThrow(NotFoundMemberException::new);
}
}

View File

@@ -4,6 +4,7 @@ import myblog.blog.member.application.port.incomming.response.userinfo.GoogleUse
import myblog.blog.member.application.port.incomming.response.userinfo.NaverUserInfo;
import myblog.blog.member.application.port.incomming.response.userinfo.Oauth2UserInfo;
import myblog.blog.member.application.port.incomming.response.userinfo.ProviderType;
import myblog.blog.member.doamin.NotSupportSocialProviderException;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Component;
@@ -41,7 +42,7 @@ public class UserInfoFactory {
public Oauth2UserInfo makeOauth2UserInfoOf(String registrationId, OAuth2User oAuth2User) {
var providerTypeOptional = createEnumFromString(registrationId);
return userInfoFactoryMap
.get(providerTypeOptional.orElseThrow(() -> new IllegalArgumentException("지원하지 않는 소셜 로그인 API 제공자입니다.")))
.get(providerTypeOptional.orElseThrow(NotSupportSocialProviderException::new))
.apply(oAuth2User);
}

View File

@@ -0,0 +1,6 @@
package myblog.blog.member.doamin;
import myblog.blog.shared.domain.ResourceNotFoundException;
public class NotFoundMemberException extends ResourceNotFoundException {
}

View File

@@ -0,0 +1,6 @@
package myblog.blog.member.doamin;
import myblog.blog.shared.domain.BadRequestException;
public class NotSupportSocialProviderException extends BadRequestException {
}

View File

@@ -0,0 +1,26 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 400 - 요청 문법상 오류
public class BadRequestException extends BusinessException{
public BadRequestException() {
}
public BadRequestException(String message) {
super(message);
}
// for rest
@Override
public HttpStatus getHttpStatus(){
return HttpStatus.BAD_REQUEST;
};
// for monitoring
@Override
public boolean isNecessaryToLog(){
return false;
};
}

View File

@@ -0,0 +1,20 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 비지니스상 개발자가 인지하는 예외 정의, 해당 예외 이외의 예외발생시는 긴급 모니터링 대상!
public abstract class BusinessException extends RuntimeException{
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
// for rest
public abstract HttpStatus getHttpStatus();
// for monitoring
public abstract boolean isNecessaryToLog();
}

View File

@@ -0,0 +1,26 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 인지된 500대 에러
public class ExternalErrorException extends BusinessException{
public ExternalErrorException() {
}
public ExternalErrorException(String message) {
super(message);
}
// for rest
@Override
public HttpStatus getHttpStatus(){
return HttpStatus.INTERNAL_SERVER_ERROR;
};
// for monitoring
@Override
public boolean isNecessaryToLog(){
return true;
};
}

View File

@@ -0,0 +1,26 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 인지된 500대 에러
public class InternalErrorException extends BusinessException{
public InternalErrorException() {
}
public InternalErrorException(String message) {
super(message);
}
// for rest
@Override
public HttpStatus getHttpStatus(){
return HttpStatus.INTERNAL_SERVER_ERROR;
};
// for monitoring
@Override
public boolean isNecessaryToLog(){
return true;
};
}

View File

@@ -0,0 +1,26 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 403 접근권한없음
public class NotAuthorizedException extends BusinessException{
public NotAuthorizedException() {
}
public NotAuthorizedException(String message) {
super(message);
}
// for rest
@Override
public HttpStatus getHttpStatus(){
return HttpStatus.FORBIDDEN;
};
// for monitoring
@Override
public boolean isNecessaryToLog(){
return false;
};
}

View File

@@ -0,0 +1,26 @@
package myblog.blog.shared.domain;
import org.springframework.http.HttpStatus;
// 404 - 리소스 찾을수 없음
public class ResourceNotFoundException extends BusinessException{
public ResourceNotFoundException() {
}
public ResourceNotFoundException(String message) {
super(message);
}
// for rest
@Override
public HttpStatus getHttpStatus(){
return HttpStatus.NOT_FOUND;
};
// for monitoring
@Override
public boolean isNecessaryToLog(){
return false;
};
}