diff --git a/src/main/java/com/libraryman_api/book/BookService.java b/src/main/java/com/libraryman_api/book/BookService.java index 665e83c..32fac54 100644 --- a/src/main/java/com/libraryman_api/book/BookService.java +++ b/src/main/java/com/libraryman_api/book/BookService.java @@ -4,8 +4,10 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.stereotype.Service; +import com.libraryman_api.exception.InvalidSortFieldException; import com.libraryman_api.exception.ResourceNotFoundException; /** @@ -42,9 +44,14 @@ public BookService(BookRepository bookRepository) { * * @param pageable the pagination information, including the page number and size * @return a {@link Page} of {@link Book} representing all books + * @throws InvalidSortFieldException if an invalid sortBy field is specified */ public Page getAllBooks(Pageable pageable) { - return bookRepository.findAll(pageable); + try { + return bookRepository.findAll(pageable); + } catch (PropertyReferenceException ex) { + throw new InvalidSortFieldException("The specified 'sortBy' value is invalid."); + } } /** diff --git a/src/main/java/com/libraryman_api/borrowing/BorrowingService.java b/src/main/java/com/libraryman_api/borrowing/BorrowingService.java index 150510e..3a7d785 100644 --- a/src/main/java/com/libraryman_api/borrowing/BorrowingService.java +++ b/src/main/java/com/libraryman_api/borrowing/BorrowingService.java @@ -3,6 +3,7 @@ import com.libraryman_api.book.BookService; import com.libraryman_api.book.Book; import com.libraryman_api.fine.Fines; +import com.libraryman_api.exception.InvalidSortFieldException; import com.libraryman_api.exception.ResourceNotFoundException; import com.libraryman_api.fine.FineRepository; import com.libraryman_api.member.MemberService; @@ -11,6 +12,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; @@ -66,9 +68,14 @@ public BorrowingService(BorrowingRepository borrowingRepository, FineRepository * * @param pageable the pagination information, including the page number and size * @return a {@link Page} of {@link Borrowings} representing all borrowings + * @throws InvalidSortFieldException if an invalid sortBy field is specified */ public Page getAllBorrowings(Pageable pageable) { - return borrowingRepository.findAll(pageable); + try { + return borrowingRepository.findAll(pageable); + } catch (PropertyReferenceException ex) { + throw new InvalidSortFieldException("The specified 'sortBy' value is invalid."); + } } /** @@ -264,14 +271,19 @@ private BigDecimal calculateFineAmount(Borrowings borrowing) { * @param memberId the ID of the member whose borrowings are to be retrieved * @param pageable the pagination information, including the page number and size * @throws ResourceNotFoundException if the member has not borrowed any books + * @throws InvalidSortFieldException if an invalid sortBy field is specified * @return a {@link Page} of {@link Borrowings} representing all borrowing associated with a specific member */ - public Page getAllBorrowingsOfMember(int memberId, Pageable pageable) { - Page borrowings = borrowingRepository.findByMember_memberId(memberId, pageable); - - if (borrowings.isEmpty()) { - throw new ResourceNotFoundException("Member didn't borrow any book"); + public Page getAllBorrowingsOfMember(int memberId, Pageable pageable) { + try { + Page borrowings = borrowingRepository.findByMember_memberId(memberId, pageable); + + if (borrowings.isEmpty()) { + throw new ResourceNotFoundException("Member didn't borrow any book"); + } + return borrowings; + } catch (PropertyReferenceException ex) { + throw new InvalidSortFieldException("The specified 'sortBy' value is invalid."); } - return borrowings; } } diff --git a/src/main/java/com/libraryman_api/exception/GlobalExceptionHandler.java b/src/main/java/com/libraryman_api/exception/GlobalExceptionHandler.java index 26704ef..a9202d3 100644 --- a/src/main/java/com/libraryman_api/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/libraryman_api/exception/GlobalExceptionHandler.java @@ -31,4 +31,20 @@ public ResponseEntity resourceNotFoundException(ResourceNotFoundException ex, ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); } + + /** + * Handles {@link InvalidSortFieldException} exceptions. + * This method is triggered when an {@code InvalidSortFieldException} is thrown in the application. + * It constructs an {@link ErrorDetails} object containing the exception details and returns + * a {@link ResponseEntity} with an HTTP status of {@code 400 Bad Request}. + * + * @param ex the exception that was thrown. + * @param request the current web request in which the exception was thrown. + * @return a {@link ResponseEntity} containing the {@link ErrorDetails} and an HTTP status of {@code 400 Bad Request}. + */ + @ExceptionHandler(InvalidSortFieldException.class) + public ResponseEntity invalidSortFieldException(InvalidSortFieldException ex, WebRequest request) { + ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false)); + return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/com/libraryman_api/exception/InvalidSortFieldException.java b/src/main/java/com/libraryman_api/exception/InvalidSortFieldException.java new file mode 100644 index 0000000..e757a40 --- /dev/null +++ b/src/main/java/com/libraryman_api/exception/InvalidSortFieldException.java @@ -0,0 +1,51 @@ +package com.libraryman_api.exception; + +import java.io.Serial; + +/** + * Custom exception class to handle scenarios where an invalid sort field + * is provided for API requests in the Library Management System. + * This exception is thrown when a sorting operation is attempted + * using a field that does not exist or is not supported. + */ +public class InvalidSortFieldException extends RuntimeException { + + /** + * The {@code serialVersionUID} is a unique identifier for each version of a serializable class. + * It is used during the deserialization process to verify that the sender and receiver of a + * serialized object have loaded classes for that object that are compatible with each other. + * + * The {@code serialVersionUID} field is important for ensuring that a serialized class + * (especially when transmitted over a network or saved to disk) can be successfully deserialized, + * even if the class definition changes in later versions. If the {@code serialVersionUID} does not + * match during deserialization, an {@code InvalidClassException} is thrown. + * + * This field is optional, but it is good practice to explicitly declare it to prevent + * automatic generation, which could lead to compatibility issues when the class structure changes. + * + * The {@code @Serial} annotation is used here to indicate that this field is related to + * serialization. This annotation is available starting from Java 14 and helps improve clarity + * regarding the purpose of this field. + */ + @Serial + private static final long serialVersionUID = 1L; + + /** + * Constructs a new {@code InvalidSortFieldException} with the specified detail message. + * + * @param message the detail message explaining the reason for the exception + */ + public InvalidSortFieldException(String message) { + super(message); + } + + /** + * Constructs a new {@code InvalidSortFieldException} with the specified detail message and cause. + * + * @param message the detail message explaining the reason for the exception + * @param cause the cause of the exception (which is saved for later retrieval by the {@link #getCause()} method) + */ + public InvalidSortFieldException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/libraryman_api/member/MemberService.java b/src/main/java/com/libraryman_api/member/MemberService.java index 93c8843..e5c4d2a 100644 --- a/src/main/java/com/libraryman_api/member/MemberService.java +++ b/src/main/java/com/libraryman_api/member/MemberService.java @@ -4,8 +4,10 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.stereotype.Service; +import com.libraryman_api.exception.InvalidSortFieldException; import com.libraryman_api.exception.ResourceNotFoundException; import com.libraryman_api.notification.NotificationService; @@ -46,9 +48,14 @@ public MemberService(MemberRepository memberRepository, NotificationService noti * * @param pageable the pagination information, including the page number and size * @return a {@link Page} of {@link Members} representing all members + * @throws InvalidSortFieldException if an invalid sortBy field is specified */ public Page getAllMembers(Pageable pageable) { - return memberRepository.findAll(pageable); + try { + return memberRepository.findAll(pageable); + } catch (PropertyReferenceException ex) { + throw new InvalidSortFieldException("The specified 'sortBy' value is invalid."); + } } /**