diff --git a/src/main/java/com/openisle/controller/GlobalExceptionHandler.java b/src/main/java/com/openisle/controller/GlobalExceptionHandler.java index e093748e9..bd7638dba 100644 --- a/src/main/java/com/openisle/controller/GlobalExceptionHandler.java +++ b/src/main/java/com/openisle/controller/GlobalExceptionHandler.java @@ -4,6 +4,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import com.openisle.exception.FieldException; +import com.openisle.exception.NotFoundException; import java.util.Map; @@ -16,6 +17,11 @@ public class GlobalExceptionHandler { .body(Map.of("error", ex.getMessage(), "field", ex.getField())); } + @ExceptionHandler(NotFoundException.class) + public ResponseEntity handleNotFoundException(NotFoundException ex) { + return ResponseEntity.status(404).body(Map.of("error", ex.getMessage())); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception ex) { return ResponseEntity.badRequest().body(Map.of("error", ex.getMessage())); diff --git a/src/main/java/com/openisle/exception/NotFoundException.java b/src/main/java/com/openisle/exception/NotFoundException.java new file mode 100644 index 000000000..875c41bfb --- /dev/null +++ b/src/main/java/com/openisle/exception/NotFoundException.java @@ -0,0 +1,10 @@ +package com.openisle.exception; + +/** + * Exception representing a missing resource such as a post or user. + */ +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/openisle/service/AiUsageService.java b/src/main/java/com/openisle/service/AiUsageService.java index 70c2d6e1b..851cfa309 100644 --- a/src/main/java/com/openisle/service/AiUsageService.java +++ b/src/main/java/com/openisle/service/AiUsageService.java @@ -29,7 +29,7 @@ public class AiUsageService { public int incrementAndGetCount(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); LocalDate today = LocalDate.now(); AiFormatUsage usage = usageRepository.findByUserAndUseDate(user, today) .orElseGet(() -> { @@ -46,7 +46,7 @@ public class AiUsageService { public int getCount(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return usageRepository.findByUserAndUseDate(user, LocalDate.now()) .map(AiFormatUsage::getCount) .orElse(0); diff --git a/src/main/java/com/openisle/service/CommentService.java b/src/main/java/com/openisle/service/CommentService.java index 262bb0367..77780a630 100644 --- a/src/main/java/com/openisle/service/CommentService.java +++ b/src/main/java/com/openisle/service/CommentService.java @@ -34,9 +34,9 @@ public class CommentService { public Comment addComment(String username, Long postId, String content) { User author = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); Comment comment = new Comment(); comment.setAuthor(author); comment.setPost(post); @@ -60,7 +60,7 @@ public class CommentService { public Comment addReply(String username, Long parentId, String content) { User author = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Comment parent = commentRepository.findById(parentId) .orElseThrow(() -> new IllegalArgumentException("Comment not found")); Comment comment = new Comment(); @@ -92,7 +92,7 @@ public class CommentService { public List getCommentsForPost(Long postId) { Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); return commentRepository.findByPostAndParentIsNullOrderByCreatedAtAsc(post); } @@ -104,14 +104,14 @@ public class CommentService { public List getRecentCommentsByUser(String username, int limit) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Pageable pageable = PageRequest.of(0, limit); return commentRepository.findByAuthorOrderByCreatedAtDesc(user, pageable); } public java.util.List getParticipants(Long postId, int limit) { Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); java.util.LinkedHashSet set = new java.util.LinkedHashSet<>(); set.add(post.getAuthor()); set.addAll(commentRepository.findDistinctAuthorsByPost(post)); @@ -126,7 +126,7 @@ public class CommentService { @org.springframework.transaction.annotation.Transactional public void deleteComment(String username, Long id) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Comment comment = commentRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Comment not found")); if (!user.getId().equals(comment.getAuthor().getId()) && user.getRole() != Role.ADMIN) { diff --git a/src/main/java/com/openisle/service/DraftService.java b/src/main/java/com/openisle/service/DraftService.java index 794828d50..86efd85c2 100644 --- a/src/main/java/com/openisle/service/DraftService.java +++ b/src/main/java/com/openisle/service/DraftService.java @@ -28,7 +28,7 @@ public class DraftService { @Transactional public Draft saveDraft(String username, Long categoryId, String title, String content, List tagIds) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Draft draft = draftRepository.findByAuthor(user).orElse(new Draft()); draft.setAuthor(user); draft.setTitle(title); diff --git a/src/main/java/com/openisle/service/NotificationService.java b/src/main/java/com/openisle/service/NotificationService.java index 3d0c9af59..1859ea2f0 100644 --- a/src/main/java/com/openisle/service/NotificationService.java +++ b/src/main/java/com/openisle/service/NotificationService.java @@ -34,7 +34,7 @@ public class NotificationService { public List listNotifications(String username, Boolean read) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); if (read == null) { return notificationRepository.findByUserOrderByCreatedAtDesc(user); } @@ -43,7 +43,7 @@ public class NotificationService { public void markRead(String username, List ids) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); List notifs = notificationRepository.findAllById(ids); for (Notification n : notifs) { if (n.getUser().getId().equals(user.getId())) { @@ -55,7 +55,7 @@ public class NotificationService { public long countUnread(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return notificationRepository.countByUserAndRead(user, false); } } diff --git a/src/main/java/com/openisle/service/PostReadService.java b/src/main/java/com/openisle/service/PostReadService.java index 029bbde0f..35fcddf69 100644 --- a/src/main/java/com/openisle/service/PostReadService.java +++ b/src/main/java/com/openisle/service/PostReadService.java @@ -21,9 +21,9 @@ public class PostReadService { public void recordRead(String username, Long postId) { if (username == null) return; User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); postReadRepository.findByUserAndPost(user, post).ifPresentOrElse(pr -> { pr.setLastReadAt(LocalDateTime.now()); postReadRepository.save(pr); @@ -38,7 +38,7 @@ public class PostReadService { public long countReads(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return postReadRepository.countByUser(user); } diff --git a/src/main/java/com/openisle/service/PostService.java b/src/main/java/com/openisle/service/PostService.java index 1a0522fb5..adb2bb8ea 100644 --- a/src/main/java/com/openisle/service/PostService.java +++ b/src/main/java/com/openisle/service/PostService.java @@ -90,7 +90,7 @@ public class PostService { throw new IllegalArgumentException("At most two tags allowed"); } User author = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Category category = categoryRepository.findById(categoryId) .orElseThrow(() -> new IllegalArgumentException("Category not found")); java.util.List tags = tagRepository.findAllById(tagIds); @@ -132,15 +132,15 @@ public class PostService { public Post viewPost(Long id, String viewer) { Post post = postRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); if (post.getStatus() != PostStatus.PUBLISHED) { if (viewer == null) { - throw new IllegalArgumentException("Post not found"); + throw new com.openisle.exception.NotFoundException("Post not found"); } User viewerUser = userRepository.findByUsername(viewer) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); if (!viewerUser.getRole().equals(com.openisle.model.Role.ADMIN) && !viewerUser.getId().equals(post.getAuthor().getId())) { - throw new IllegalArgumentException("Post not found"); + throw new com.openisle.exception.NotFoundException("Post not found"); } } post.setViews(post.getViews() + 1); @@ -243,7 +243,7 @@ public class PostService { public List getRecentPostsByUser(String username, int limit) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Pageable pageable = PageRequest.of(0, limit); return postRepository.findByAuthorAndStatusOrderByCreatedAtDesc(user, PostStatus.PUBLISHED, pageable); } @@ -311,7 +311,7 @@ public class PostService { public Post approvePost(Long id) { Post post = postRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); // publish all pending tags along with the post for (com.openisle.model.Tag tag : post.getTags()) { if (!tag.isApproved()) { @@ -327,7 +327,7 @@ public class PostService { public Post rejectPost(Long id) { Post post = postRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); // remove user created tags that are only linked to this post java.util.Set tags = new java.util.HashSet<>(post.getTags()); for (com.openisle.model.Tag tag : tags) { @@ -348,9 +348,9 @@ public class PostService { @org.springframework.transaction.annotation.Transactional public void deletePost(Long id, String username) { Post post = postRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); if (!user.getId().equals(post.getAuthor().getId()) && user.getRole() != Role.ADMIN) { throw new IllegalArgumentException("Unauthorized"); } diff --git a/src/main/java/com/openisle/service/ReactionService.java b/src/main/java/com/openisle/service/ReactionService.java index 104db91c3..95ba9af99 100644 --- a/src/main/java/com/openisle/service/ReactionService.java +++ b/src/main/java/com/openisle/service/ReactionService.java @@ -25,9 +25,9 @@ public class ReactionService { public Reaction reactToPost(String username, Long postId, ReactionType type) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); java.util.Optional existing = reactionRepository.findByUserAndPostAndType(user, post, type); if (existing.isPresent()) { @@ -47,7 +47,7 @@ public class ReactionService { public Reaction reactToComment(String username, Long commentId, ReactionType type) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Comment comment = commentRepository.findById(commentId) .orElseThrow(() -> new IllegalArgumentException("Comment not found")); java.util.Optional existing = @@ -70,7 +70,7 @@ public class ReactionService { public java.util.List getReactionsForPost(Long postId) { Post post = postRepository.findById(postId) - .orElseThrow(() -> new IllegalArgumentException("Post not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); return reactionRepository.findByPost(post); } diff --git a/src/main/java/com/openisle/service/TagService.java b/src/main/java/com/openisle/service/TagService.java index 203762dd2..0f7c51abc 100644 --- a/src/main/java/com/openisle/service/TagService.java +++ b/src/main/java/com/openisle/service/TagService.java @@ -28,7 +28,7 @@ public class TagService { tag.setApproved(approved); if (creatorUsername != null) { User creator = userRepository.findByUsername(creatorUsername) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); tag.setCreator(creator); } return tagRepository.save(tag); @@ -94,14 +94,14 @@ public class TagService { public List getRecentTagsByUser(String username, int limit) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); Pageable pageable = PageRequest.of(0, limit); return tagRepository.findByCreatorOrderByCreatedAtDesc(user, pageable); } public List getTagsByUser(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return tagRepository.findByCreator(user); } } diff --git a/src/main/java/com/openisle/service/UserService.java b/src/main/java/com/openisle/service/UserService.java index 1d97097ba..bcf241e64 100644 --- a/src/main/java/com/openisle/service/UserService.java +++ b/src/main/java/com/openisle/service/UserService.java @@ -104,14 +104,14 @@ public class UserService { public User updateAvatar(String username, String avatarUrl) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); user.setAvatar(avatarUrl); return userRepository.save(user); } public User updateProfile(String currentUsername, String newUsername, String introduction) { User user = userRepository.findByUsername(currentUsername) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); if (newUsername != null && !newUsername.equals(currentUsername)) { usernameValidator.validate(newUsername); userRepository.findByUsername(newUsername).ifPresent(u -> { diff --git a/src/main/java/com/openisle/service/UserVisitService.java b/src/main/java/com/openisle/service/UserVisitService.java index 305c860c3..7ae912851 100644 --- a/src/main/java/com/openisle/service/UserVisitService.java +++ b/src/main/java/com/openisle/service/UserVisitService.java @@ -17,7 +17,7 @@ public class UserVisitService { public void recordVisit(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); LocalDate today = LocalDate.now(); userVisitRepository.findByUserAndVisitDate(user, today).orElseGet(() -> { UserVisit visit = new UserVisit(); @@ -29,7 +29,7 @@ public class UserVisitService { public long countVisits(String username) { User user = userRepository.findByUsername(username) - .orElseThrow(() -> new IllegalArgumentException("User not found")); + .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return userVisitRepository.countByUser(user); } }