Skip to content

Commit fd39fd6

Browse files
authored
refactor: added tour & bookmark exception (#53)
1 parent 37ab50a commit fd39fd6

File tree

6 files changed

+116
-5
lines changed

6 files changed

+116
-5
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.jocketdan.tour.exception;
2+
3+
import jakarta.servlet.http.HttpServletRequest;
4+
import java.time.LocalDateTime;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.ExceptionHandler;
9+
import org.springframework.web.bind.annotation.RestControllerAdvice;
10+
11+
@Slf4j
12+
@RestControllerAdvice
13+
public class CommonExceptionHandler {
14+
15+
@ExceptionHandler(CustomException.class)
16+
public ResponseEntity<ErrorDetail> handler(HttpServletRequest request, CustomException e) {
17+
ExceptionType type = e.getType();
18+
HttpStatus status = type.getStatus();
19+
20+
ErrorDetail detail = ErrorDetail.builder()
21+
.errorCode(type.getCustomCode())
22+
.errorMessage(e.getMessage())
23+
.path(request.getRequestURI())
24+
.status(status.value())
25+
.timestamp(LocalDateTime.now())
26+
.build();
27+
28+
return ResponseEntity.status(status).body(detail);
29+
}
30+
31+
@ExceptionHandler(Exception.class)
32+
public ResponseEntity<ErrorDetail> handler(HttpServletRequest request, Exception e) {
33+
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
34+
35+
ErrorDetail detail = ErrorDetail.builder()
36+
.errorCode("999")
37+
.errorMessage(e.getMessage())
38+
.path(request.getRequestURI())
39+
.status(status.value())
40+
.timestamp(LocalDateTime.now())
41+
.build();
42+
43+
return ResponseEntity.status(status).body(detail);
44+
}
45+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.jocketdan.tour.exception;
2+
3+
import lombok.Getter;
4+
5+
@Getter
6+
public class CustomException extends RuntimeException {
7+
private final ExceptionType type;
8+
9+
public CustomException(ExceptionType type) {
10+
super(type.getMessage());
11+
this.type = type;
12+
}
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.jocketdan.tour.exception;
2+
3+
import java.time.LocalDateTime;
4+
import lombok.AccessLevel;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.experimental.FieldDefaults;
9+
10+
@Builder
11+
@Getter
12+
@RequiredArgsConstructor
13+
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
14+
public class ErrorDetail {
15+
16+
String errorCode;
17+
String errorMessage;
18+
String path;
19+
Integer status;
20+
LocalDateTime timestamp;
21+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.jocketdan.tour.exception;
2+
3+
import lombok.AccessLevel;
4+
import lombok.Getter;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.experimental.FieldDefaults;
7+
import org.springframework.http.HttpStatus;
8+
9+
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
10+
@Getter
11+
@RequiredArgsConstructor
12+
public enum ExceptionType {
13+
14+
ALREADY_EXITED_BOOKMARK(HttpStatus.CONFLICT, "300", "이미 북마크에 추가된 장소입니다."),
15+
BOOKMARK_NOT_FOUND(HttpStatus.NOT_FOUND, "301", "삭제할 북마크가 없습니다."),
16+
CANNOT_PARSE_ID(HttpStatus.INTERNAL_SERVER_ERROR, "303", "컨텐츠 타입 형변환 실패입니다."),
17+
18+
PLACE_NOT_FOUND(HttpStatus.CONFLICT, "351", "존재하지 않는 장소입니다.");
19+
20+
HttpStatus status;
21+
String customCode;
22+
String message;
23+
}

tour/src/main/java/com/jocketdan/tour/service/BookmarkService.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@
44
import com.jocketdan.tour.entity.Bookmark;
55
import com.jocketdan.tour.entity.BookmarkType;
66
import com.jocketdan.tour.entity.OpenApiPlaceDetail;
7+
import com.jocketdan.tour.exception.CustomException;
8+
import com.jocketdan.tour.exception.ExceptionType;
79
import com.jocketdan.tour.repository.BookmarkRepository;
810
import lombok.AccessLevel;
911
import lombok.RequiredArgsConstructor;
1012
import lombok.experimental.FieldDefaults;
13+
import lombok.extern.slf4j.Slf4j;
1114
import org.springframework.data.domain.Page;
1215
import org.springframework.data.domain.Pageable;
1316
import org.springframework.stereotype.Service;
1417
import org.springframework.transaction.annotation.Transactional;
1518

1619
import java.util.List;
1720

21+
@Slf4j
1822
@Service
1923
@RequiredArgsConstructor
2024
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@@ -28,7 +32,7 @@ public void addBookmark(String contentId, String userEmail) {
2832
OpenApiPlaceDetail place = tourOpenApiService.getOrFetchPlaceDetail(contentId);
2933

3034
if (bookmarkRepository.existsByUserEmailAndContentId(userEmail, place)) {
31-
throw new IllegalStateException("이미 북마크에 추가된 장소입니다.");
35+
throw new CustomException(ExceptionType.ALREADY_EXITED_BOOKMARK);
3236
}
3337

3438
Integer contentTypeId = parseContentTypeId(place.getContentTypeId());
@@ -40,7 +44,7 @@ public void addBookmark(String contentId, String userEmail) {
4044
public void removeBookmark(List<String> contentIds, String userEmail) {
4145
List<Bookmark> bookmarks = bookmarkRepository.findByUserEmailAndContentId_ContentIdIn(userEmail, contentIds);
4246
if (bookmarks.isEmpty()) {
43-
throw new IllegalArgumentException("삭제할 북마크가 없습니다.");
47+
throw new CustomException(ExceptionType.BOOKMARK_NOT_FOUND);
4448
}
4549
bookmarkRepository.deleteAllInBatch(bookmarks);
4650
}
@@ -60,8 +64,8 @@ private Integer parseContentTypeId(String contentTypeId) {
6064
try {
6165
return Integer.parseInt(contentTypeId);
6266
} catch (NumberFormatException e) {
63-
throw new IllegalStateException(
64-
"유효하지 않은 contentTypeId: " + contentTypeId, e);
67+
log.warn("parseContentTypeId ContentTypeId = {}", contentTypeId);
68+
throw new CustomException(ExceptionType.CANNOT_PARSE_ID);
6569
}
6670
}
6771
}

tour/src/main/java/com/jocketdan/tour/service/TourOpenApiService.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@
22

33
import com.jocketdan.tour.dto.openApi.*;
44
import com.jocketdan.tour.entity.OpenApiPlaceDetail;
5+
import com.jocketdan.tour.exception.CustomException;
6+
import com.jocketdan.tour.exception.ExceptionType;
57
import com.jocketdan.tour.repository.OpenApiPlaceDetailRepository;
68
import jakarta.persistence.EntityNotFoundException;
79
import lombok.AccessLevel;
810
import lombok.RequiredArgsConstructor;
911
import lombok.experimental.FieldDefaults;
12+
import lombok.extern.slf4j.Slf4j;
1013
import org.springframework.stereotype.Service;
1114
import org.springframework.transaction.annotation.Transactional;
1215

1316
import java.util.Map;
1417
import java.util.Objects;
1518

19+
@Slf4j
1620
@Service
1721
@RequiredArgsConstructor
1822
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@@ -146,7 +150,8 @@ private void validateApiResponse(DetailsResponseDTO response, String contentId)
146150
|| response.getResponse().getBody() == null
147151
|| response.getResponse().getBody().getItems() == null
148152
|| response.getResponse().getBody().getItems().getItem().isEmpty()) {
149-
throw new EntityNotFoundException("존재하지 않는 장소입니다: " + contentId);
153+
log.warn("validateApiResponse ContentId = {}", contentId);
154+
throw new CustomException(ExceptionType.PLACE_NOT_FOUND);
150155
}
151156
}
152157

0 commit comments

Comments
 (0)