Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 책 기능을 추가했습니다. #9

Closed
wants to merge 25 commits into from
Closed

feat: 책 기능을 추가했습니다. #9

wants to merge 25 commits into from

Conversation

becooq81
Copy link
Member

@becooq81 becooq81 commented Dec 3, 2024

📕 Issue Number

Closes #8

📙 작업 내역

구현 내용 및 작업 했던 내역

  • 도서 전체 조회 기능을 추가합니다.
  • 도서 상세 조회 기능을 추가합니다.
  • 도서 대여 및 반환 기능을 추가합니다.
  • 도서 등록 기능을 추가합니다.
  • 네이버 도서 검색 기능을 추가합니다.

📘 작업 유형

  • 신규 기능 추가
  • 버그 수정
  • 리펙토링
  • 문서 업데이트

📋 체크리스트

  • Merge 하는 브랜치가 올바른가?
  • 코딩컨벤션을 준수하는가?
  • PR과 관련없는 변경사항이 없는가?
  • 내 코드에 대한 자기 검토가 되었는가?
  • 변경사항이 효과적이거나 동작이 작동한다는 것을 보증하는 테스트를 추가하였는가?
  • 새로운 테스트와 기존의 테스트가 변경사항에 대해 만족하는가?

📝 PR 특이 사항

PR을 볼 때 주의깊게 봐야하거나 말하고 싶은 점

  • 반환되지 않은 대여 도서에 관한 알림은 아직 팀장님과 상의 중입니다.
  • 자동 merge가 가능하지 않습니다.



Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced README with detailed setup instructions for environment variables.
    • Introduced BookClient interface for searching books via an API.
    • Added NaverBookClient implementation for book searches using the Naver API.
    • New methods in BookController for searching, adding, updating, and managing books.
  • Improvements

    • Streamlined badge assignment logic in BadgeService.
    • Updated Book class with additional fields for better data representation.
    • Improved error handling across various book management methods.
  • Bug Fixes

    • Commented out test methods in BookAcceptanceTest for clarity.
  • Chores

    • Added configuration for Naver API in application.yml.
    • Introduced RestTemplateConfig for HTTP request management.

Copy link

coderabbitai bot commented Dec 3, 2024

Walkthrough

The changes in this pull request involve significant enhancements to the book management functionality within the application. Key modifications include the introduction of new classes and methods for book creation, updating, borrowing, and returning. A new interface and its implementation have been created to streamline these operations. Additionally, a new configuration for integrating with the Naver Book API has been added, along with improvements to the README documentation for setup instructions. The overall structure has been refined to provide clearer data transfer objects and better error handling.

Changes

File Path Change Summary
README.md Expanded "Getting Started" section with environment variable setup instructions. Added "Deploy" section. Emphasized -parameters argument in "Usage".
build.gradle Added dependencies for Jackson library: jackson-dataformat-xml, jackson-databind, jackson-annotations, jackson-core.
src/main/java/org/poolc/api/activity/domain/Session.java Added newline character at the end of the file.
src/main/java/org/poolc/api/badge/service/BadgeService.java Annotated badgeGiver method with @Transactional, simplified logic by removing badge log check.
src/main/java/org/poolc/api/book/client/BookClient.java Introduced new interface BookClient with method searchBooks.
src/main/java/org/poolc/api/book/client/NaverBookClient.java Implemented BookClient interface to search books via Naver API, added error handling for XML parsing.
src/main/java/org/poolc/api/book/controller/BookController.java Replaced and updated methods for book retrieval, addition, updating, and borrowing/returning functionality. Added error handling.
src/main/java/org/poolc/api/book/domain/Book.java Added Lombok annotations, new fields for book attributes, and modified update method.
src/main/java/org/poolc/api/book/domain/BookBorrower.java Introduced new class to map book borrowing relationships.
src/main/java/org/poolc/api/book/domain/BorrowStatus.java Added enumeration for book borrowing statuses.
src/main/java/org/poolc/api/book/dto/request/CreateBookRequest.java Added new DTO for book creation with validation constraints.
src/main/java/org/poolc/api/book/dto/request/UpdateBookRequest.java Introduced new DTO for updating book information.
src/main/java/org/poolc/api/book/dto/response/BookApiResponse.java Added DTO for handling responses from book-related API calls.
src/main/java/org/poolc/api/book/repository/BookRepository.java Added methods for finding books by ID and paginated retrieval.
src/main/java/org/poolc/api/book/service/BookService.java Transformed into an interface with new method signatures for book management operations.
src/main/java/org/poolc/api/book/service/BookServiceImpl.java Implemented the BookService interface, providing concrete methods for book management.
src/main/java/org/poolc/api/configuration/RestTemplateConfig.java Added configuration class for RestTemplate bean.
src/main/resources/application.yml Added new configuration section for Naver API credentials.
src/test/java/org/poolc/api/book/BookAcceptanceTest.java Commented out a block of test methods related to book management.
src/test/java/org/poolc/api/book/BookDataLoader.java Removed implementation of CommandLineRunner, disabling automatic data loading on startup.

Assessment against linked issues

Objective Addressed Explanation
1. Add functionality to retrieve all books.
2. Add functionality to retrieve book details.
3. Add functionality for borrowing and returning books.
4. Add functionality for registering books.
5. Add functionality for searching books via Naver API.

🐰 In the land of code so bright,
New features bloom, a wondrous sight!
Books to borrow, search, and share,
With every change, we show we care.
So hop along, let’s code away,
For in this project, we’ll play all day! 📚✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (18)
src/main/java/org/poolc/api/book/client/NaverBookClient.java (4)

49-49: Use a logging framework instead of System.out.println

Using System.out.println for output is not recommended in production code. Consider using a logging framework like SLF4J or Log4j for better control over logging levels and outputs.


56-56: Use logging instead of e.printStackTrace()

Printing stack traces directly is not suitable for production environments. Use a logging framework to log exceptions, which allows for better log management and severity levels.


57-57: Define a custom exception or use an appropriate existing one

Throwing XMLParseException from javax.management.modelmbean may not be appropriate here. Consider creating a custom exception (e.g., XmlParsingException) or using DataFormatException to represent XML parsing errors more accurately.


61-61: Specify precise exceptions in the method signature

Instead of throws Exception, specify the exact exceptions that parseBooks might throw, such as JsonProcessingException or IOException, to improve clarity and exception handling.

src/main/java/org/poolc/api/book/service/BookServiceImpl.java (1)

101-103: Use a more appropriate exception for authorization failures

Throwing an IllegalArgumentException when access is denied may not be semantically correct. Consider using AccessDeniedException or creating a custom exception to represent unauthorized access appropriately.

src/main/java/org/poolc/api/book/controller/BookController.java (1)

36-36: Specify response types explicitly in ResponseEntity

Using raw types like ResponseEntity<?> can reduce type safety. Specify the response type explicitly, such as ResponseEntity<Page<BookResponse>> or ResponseEntity<BookResponse>, to improve code clarity and maintainability.

Also applies to: 45-45, 54-54, 65-65, 75-75, 86-86, 96-96

src/main/java/org/poolc/api/book/client/BookClient.java (1)

5-5: Use an appropriate exception class for XML parsing errors

The XMLParseException from javax.management.modelmbean is intended for JMX use and may not be suitable here. Consider using XmlParseException from a more relevant package or define a custom exception to accurately represent parsing errors.

Also applies to: 10-10

src/main/java/org/poolc/api/book/repository/BookRepository.java (1)

11-14: Consider adding index hints for query optimization

The findAllByOrderByCreatedAtDesc method would benefit from an index on the createdAt column. Add the following index to the Book entity:

@Entity
public class Book {
+    @Index(name = "idx_book_created_at")
     private LocalDateTime createdAt;
src/main/java/org/poolc/api/book/dto/request/UpdateBookRequest.java (1)

7-21: Add field documentation

Consider adding Javadoc to describe the purpose and constraints of each field.

 @Getter
 @AllArgsConstructor
 @NoArgsConstructor
 public class UpdateBookRequest {
+    /**
+     * The title of the book.
+     * Must not be blank and maximum length is 255 characters.
+     */
     private String title;
+
+    /**
+     * The author of the book.
+     * Must not be blank and maximum length is 255 characters.
+     */
     private String author;
     // Add similar documentation for other fields
 }
src/main/resources/application.yml (1)

35-39: Document the new environment variables

The configuration for Naver Book API follows good security practices by using environment variables. However, these new environment variables need to be documented.

Please update the README or environment setup documentation to include:

  • NAVER_BOOK_API_URL
  • NAVER_BOOK_CLIENT_ID
  • NAVER_BOOK_CLIENT_SECRET
src/main/java/org/poolc/api/book/dto/request/CreateBookRequest.java (1)

27-28: Add maximum length constraint for description

While descriptions can be long, having no maximum length could lead to potential issues.

-    @Length(min = 1)
+    @Length(min = 1, max = 4000)
     private String description;
src/main/java/org/poolc/api/book/dto/response/BookApiResponse.java (2)

10-38: Add class-level documentation and null handling

The response DTO could benefit from better documentation and null handling:

  1. Add class-level documentation explaining the XML structure
  2. Consider using @JsonInclude to handle null values
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Response DTO for Naver Book API XML response.
+ * Maps to the following XML structure:
+ * <item>
+ *   <title>Book Title</title>
+ *   <link>Book URL</link>
+ *   ...
+ * </item>
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
 @Getter
 @Builder
 @AllArgsConstructor
 @NoArgsConstructor
 public class BookApiResponse {

24-25: Handle potential null discount values

The discount field is an Integer which could be null from the API response. Consider using an Optional or providing a default value.

     @JacksonXmlProperty(localName = "discount")
-    private Integer discount;
+    private Integer discount = 0;
src/test/java/org/poolc/api/book/BookDataLoader.java (1)

Test data setup needs to be maintained

The acceptance tests in BookAcceptanceTest.java are currently commented out and the BookDataLoader has been disabled. This is problematic because:

  1. The acceptance tests expect 7 books to exist (assertThat(response.body().jsonPath().getList("data")).hasSize(7))
  2. Tests reference specific book IDs (1L through 7L) and data ("형철이의 삶", "풀씨")
  3. No alternative test data setup mechanism (SQL files or test properties) is present

Either:

  • Restore the BookDataLoader implementation
  • Or replace it with an alternative test data setup mechanism that provides the expected test data
🔗 Analysis chain

Line range hint 14-39: Reconsider commenting out test data setup

The entire test data loader functionality has been commented out. While this might be intentional as part of the book feature refactoring, we should ensure that:

  1. Test coverage is maintained with alternative test data setup
  2. Integration tests that might have depended on this data loader are updated accordingly

Let's check for any existing test dependencies:

Would you like help creating an updated version of the test data loader that aligns with the new book features?

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for tests that might reference BookDataLoader
rg -l "BookDataLoader|@Profile.*bookTest" "src/test"

# Check for potentially affected test files
rg -l "형철이의 삶|풀씨" "src/test"

Length of output: 717


Script:

#!/bin/bash
# Let's check the content of BookAcceptanceTest to see if it depends on the commented data
cat src/test/java/org/poolc/api/book/BookAcceptanceTest.java

# Also check if there are other data loaders or setup methods for book tests
rg -l "class.*Test.*Book|@Test.*Book" src/test

Length of output: 12759


Script:

#!/bin/bash
# Let's check if there are any other active test data setup mechanisms
rg -A 5 "@Profile.*bookTest" src/test

# Check for any SQL data setup files
fd -e sql . src/test

# Check for any other test configuration files
fd -e yaml -e properties . src/test/resources

Length of output: 588

src/main/java/org/poolc/api/book/dto/response/NaverApiResponse.java (2)

27-38: Consider adding validation annotations

The Channel class fields (lastBuildDate, total, start, display) lack validation annotations. Consider adding:

  • @NotNull for required fields
  • @Min(0) for numeric fields that should be non-negative
  • @Size constraints for the items list

Example implementation:

+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;

     @JacksonXmlProperty(localName="total")
+    @NotNull
+    @Min(0)
     private Integer total;

     @JacksonXmlProperty(localName="start")
+    @NotNull
+    @Min(0)
     private Integer start;

     @JacksonXmlProperty(localName="display")
+    @NotNull
+    @Min(0)
     private Integer display;

39-41: Add documentation for XML wrapper configuration

The @JacksonXmlElementWrapper(useWrapping = false) configuration is crucial for correct XML parsing. Consider adding a comment explaining why this configuration is needed.

+    // Disable XML wrapping since Naver API returns items directly under channel
+    // without an additional wrapper element
     @JacksonXmlProperty(localName = "item")
     @JacksonXmlElementWrapper(useWrapping = false)
     private List<BookApiResponse> items;
src/main/java/org/poolc/api/book/dto/response/BookResponse.java (1)

18-29: Consider adding validation annotations for response fields

To ensure data integrity, consider adding validation annotations to the fields. This is especially important for fields that should never be null in the response.

+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.NotBlank;

+    @NotNull
     private Long id;
+    @NotBlank
     private String title;
     private String link;
     private String imageURL;
+    @NotBlank
     private String author;
     private String description;
     private Integer discount;
     private String isbn;
     private String publisher;
     private String publishedDate;
     private LocalDate borrowDate;
+    @NotNull
     private BookStatus status;
src/main/java/org/poolc/api/book/domain/Book.java (1)

35-45: Consider adding validation constraints for title and author

While nullable constraints are set correctly, consider adding length constraints to prevent extremely long titles or author names that might cause display issues.

-    @Column(name = "title", nullable = false)
+    @Column(name = "title", nullable = false)
+    @Size(max = 255)
     private String title;

-    @Column(name = "author", nullable = false)
+    @Column(name = "author", nullable = false)
+    @Size(max = 255)
     private String author;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4ca93f9 and d29e3c3.

📒 Files selected for processing (27)
  • README.md (0 hunks)
  • build.gradle (1 hunks)
  • src/main/java/org/poolc/api/activity/domain/Session.java (1 hunks)
  • src/main/java/org/poolc/api/badge/service/BadgeService.java (1 hunks)
  • src/main/java/org/poolc/api/book/client/BookClient.java (1 hunks)
  • src/main/java/org/poolc/api/book/client/NaverBookClient.java (1 hunks)
  • src/main/java/org/poolc/api/book/controller/BookController.java (1 hunks)
  • src/main/java/org/poolc/api/book/domain/Book.java (4 hunks)
  • src/main/java/org/poolc/api/book/domain/BookBorrower.java (1 hunks)
  • src/main/java/org/poolc/api/book/domain/BorrowStatus.java (1 hunks)
  • src/main/java/org/poolc/api/book/dto/BookRequest.java (0 hunks)
  • src/main/java/org/poolc/api/book/dto/BookResponse.java (0 hunks)
  • src/main/java/org/poolc/api/book/dto/request/CreateBookRequest.java (1 hunks)
  • src/main/java/org/poolc/api/book/dto/request/UpdateBookRequest.java (1 hunks)
  • src/main/java/org/poolc/api/book/dto/response/BookApiResponse.java (1 hunks)
  • src/main/java/org/poolc/api/book/dto/response/BookResponse.java (1 hunks)
  • src/main/java/org/poolc/api/book/dto/response/NaverApiResponse.java (1 hunks)
  • src/main/java/org/poolc/api/book/repository/BookRepository.java (1 hunks)
  • src/main/java/org/poolc/api/book/service/BookService.java (1 hunks)
  • src/main/java/org/poolc/api/book/service/BookServiceImpl.java (1 hunks)
  • src/main/java/org/poolc/api/book/vo/BookCreateValues.java (0 hunks)
  • src/main/java/org/poolc/api/book/vo/BookUpdateValues.java (0 hunks)
  • src/main/java/org/poolc/api/book/vo/BorrowerValues.java (0 hunks)
  • src/main/java/org/poolc/api/configuration/RestTemplateConfig.java (1 hunks)
  • src/main/resources/application.yml (1 hunks)
  • src/test/java/org/poolc/api/book/BookAcceptanceTest.java (2 hunks)
  • src/test/java/org/poolc/api/book/BookDataLoader.java (2 hunks)
💤 Files with no reviewable changes (6)
  • src/main/java/org/poolc/api/book/vo/BookUpdateValues.java
  • src/main/java/org/poolc/api/book/vo/BorrowerValues.java
  • src/main/java/org/poolc/api/book/dto/BookRequest.java
  • README.md
  • src/main/java/org/poolc/api/book/vo/BookCreateValues.java
  • src/main/java/org/poolc/api/book/dto/BookResponse.java
✅ Files skipped from review due to trivial changes (4)
  • src/main/java/org/poolc/api/activity/domain/Session.java
  • src/main/java/org/poolc/api/book/domain/BorrowStatus.java
  • src/main/java/org/poolc/api/book/domain/BookBorrower.java
  • src/test/java/org/poolc/api/book/BookAcceptanceTest.java
🔇 Additional comments (2)
src/main/java/org/poolc/api/book/domain/Book.java (1)

4-5: LGTM: Entity annotations are well-structured

The addition of @AllArgsConstructor and @Builder annotations facilitates clean object creation, especially useful for the book registration feature.

Also applies to: 21-21, 23-23

src/main/java/org/poolc/api/badge/service/BadgeService.java (1)

142-151: LGTM: Transaction management properly implemented

The addition of @transactional and the duplicate check logic ensures data consistency when giving badges.

Comment on lines +14 to +17
void deleteBook(Member member, Long id) throws Exception;
void updateBook(Member member, Long id, UpdateBookRequest request) throws Exception;
void borrow(Member member, Long id) throws Exception;
void returnBook(Member member, Long id) throws Exception;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Specify more specific exceptions instead of 'throws Exception'

Using throws Exception in method declarations is too broad and can obscure the exact nature of exceptions that might be thrown. It's better to declare specific exceptions to improve code clarity and error handling.

Comment on lines +55 to +58
} catch (Exception e) {
e.printStackTrace();
throw new XMLParseException("Failed to parse XML response");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid catching generic Exception; catch specific exceptions

Catching a generic Exception can make debugging harder and may catch exceptions you didn't intend to handle. Catch specific exceptions like IOException, HttpClientErrorException, or XmlMappingException to handle known error cases.

public void deleteBook(Member member, Long id) throws Exception {
checkAdmin(member);
Book book = bookRepository.findById(id)
.orElseThrow(() -> new Exception("책을 찾을 없습니다. id: " + id));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid throwing generic Exception; use specific exception classes

Throwing generic exceptions reduces the specificity of error handling. Use more specific exceptions like NoSuchElementException, IllegalStateException, or define custom exceptions to provide clearer context and improve maintainability.

Also applies to: 65-65, 73-75, 85-89

Comment on lines +29 to +32
return new ResponseEntity<>(bookClient.searchBooks(query, page), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid returning exception messages directly in API responses

Returning e.getMessage() to the client can expose sensitive information and is a security risk. Instead, return user-friendly error messages and use appropriate HTTP status codes like BAD_REQUEST, NOT_FOUND, or FORBIDDEN based on the error type.

Also applies to: 38-41, 47-50, 57-61, 67-71, 78-82, 88-92, 98-102

Comment on lines +10 to +13
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance RestTemplate configuration for production readiness

The current RestTemplate configuration lacks essential production-ready features. Consider adding:

  • Connection/read timeout settings
  • Error handling
  • SSL configuration
  • Retry mechanism for transient failures
@Bean
public RestTemplate restTemplate() {
-    return new RestTemplate();
+    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
+    factory.setConnectTimeout(5000);
+    factory.setReadTimeout(5000);
+    
+    RestTemplate restTemplate = new RestTemplate(factory);
+    
+    restTemplate.setErrorHandler(new ResponseErrorHandler() {
+        @Override
+        public boolean hasError(ClientHttpResponse response) throws IOException {
+            return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
+                || response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;
+        }
+        
+        @Override
+        public void handleError(ClientHttpResponse response) throws IOException {
+            throw new RestClientException("API call failed: " + response.getStatusCode());
+        }
+    });
+    
+    return restTemplate;

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +24 to +25
@Length(min = 1, max = 100)
private String isbn;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Strengthen ISBN validation

The current validation only checks length. Consider adding a pattern validation for ISBN format.

-    @Length(min = 1, max = 100)
+    @Length(min = 10, max = 13)
+    @Pattern(regexp = "^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$")
     private String isbn;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Length(min = 1, max = 100)
private String isbn;
@Length(min = 10, max = 13)
@Pattern(regexp = "^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$")
private String isbn;

Comment on lines +31 to +46
public static BookResponse of(Book book) {
return BookResponse.builder()
.id(book.getId())
.title(book.getTitle())
.link(book.getLink())
.imageURL(book.getImageURL())
.author(book.getAuthor())
.description(book.getDescription())
.discount(book.getDiscount())
.isbn(book.getIsbn())
.publisher(book.getPublisher())
.publishedDate(book.getPublishedDate())
.borrowDate(book.getBorrowDate())
.status(book.getStatus())
.build();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null checks and documentation to factory method

The of method should handle null values gracefully and include documentation for maintainability.

Consider adding:

  1. Null check for the input parameter
  2. JavaDoc explaining the method's purpose
  3. Null-safe getters
+    /**
+     * Creates a BookResponse DTO from a Book domain object.
+     *
+     * @param book the source Book object
+     * @return a new BookResponse instance
+     * @throws IllegalArgumentException if book is null
+     */
     public static BookResponse of(Book book) {
+        if (book == null) {
+            throw new IllegalArgumentException("Book cannot be null");
+        }
         return BookResponse.builder()
                 .id(book.getId())
                 .title(book.getTitle())
                 .link(book.getLink())
                 .imageURL(book.getImageURL())
                 .author(book.getAuthor())
                 .description(book.getDescription())
                 .discount(book.getDiscount())
                 .isbn(book.getIsbn())
                 .publisher(book.getPublisher())
                 .publishedDate(book.getPublishedDate())
                 .borrowDate(book.getBorrowDate())
                 .status(book.getStatus())
                 .build();
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static BookResponse of(Book book) {
return BookResponse.builder()
.id(book.getId())
.title(book.getTitle())
.link(book.getLink())
.imageURL(book.getImageURL())
.author(book.getAuthor())
.description(book.getDescription())
.discount(book.getDiscount())
.isbn(book.getIsbn())
.publisher(book.getPublisher())
.publishedDate(book.getPublishedDate())
.borrowDate(book.getBorrowDate())
.status(book.getStatus())
.build();
}
/**
* Creates a BookResponse DTO from a Book domain object.
*
* @param book the source Book object
* @return a new BookResponse instance
* @throws IllegalArgumentException if book is null
*/
public static BookResponse of(Book book) {
if (book == null) {
throw new IllegalArgumentException("Book cannot be null");
}
return BookResponse.builder()
.id(book.getId())
.title(book.getTitle())
.link(book.getLink())
.imageURL(book.getImageURL())
.author(book.getAuthor())
.description(book.getDescription())
.discount(book.getDiscount())
.isbn(book.getIsbn())
.publisher(book.getPublisher())
.publishedDate(book.getPublishedDate())
.borrowDate(book.getBorrowDate())
.status(book.getStatus())
.build();
}

Comment on lines +84 to +93
public void update(UpdateBookRequest request) {
if (request.getTitle() != null) this.title = request.getTitle();
if (request.getLink() != null) this.link = request.getLink();
if (request.getImage() != null) this.imageURL = request.getImage();
if (request.getAuthor() != null) this.author = request.getAuthor();
if (request.getDescription() != null) this.description = request.getDescription();
if (request.getDiscount() != null) this.discount = request.getDiscount();
if (request.getIsbn() != null) this.isbn = request.getIsbn();
if (request.getPublisher() != null) this.publisher = request.getPublisher();
if (request.getPubdate() != null) this.publishedDate = request.getPubdate();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance update method with validation and audit logging

The current implementation should validate input values before updating and consider logging changes for audit purposes.

     public void update(UpdateBookRequest request) {
+        validateUpdateRequest(request);
+        logBookChanges(request);
         if (request.getTitle() != null) this.title = request.getTitle();
         if (request.getLink() != null) this.link = request.getLink();
         if (request.getImage() != null) this.imageURL = request.getImage();
         if (request.getAuthor() != null) this.author = request.getAuthor();
         if (request.getDescription() != null) this.description = request.getDescription();
         if (request.getDiscount() != null) this.discount = request.getDiscount();
         if (request.getIsbn() != null) this.isbn = request.getIsbn();
         if (request.getPublisher() != null) this.publisher = request.getPublisher();
         if (request.getPubdate() != null) this.publishedDate = request.getPubdate();
     }
+    
+    private void validateUpdateRequest(UpdateBookRequest request) {
+        if (request.getDiscount() != null && request.getDiscount() < 0) {
+            throw new IllegalArgumentException("Discount cannot be negative");
+        }
+        // Add more validations as needed
+    }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +53 to +60
@Column(name = "isbn")
private String isbn;

@Column(name = "publisher")
private String publisher;

@Column(name = "published_date")
private String publishedDate;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation for ISBN and publishedDate fields

The ISBN field should validate against standard formats, and publishedDate should follow a consistent date format.

-    @Column(name = "isbn")
+    @Column(name = "isbn")
+    @Pattern(regexp = "^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$")
     private String isbn;

-    @Column(name = "published_date")
+    @Column(name = "published_date")
+    @Pattern(regexp = "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$")
     private String publishedDate;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Column(name = "isbn")
private String isbn;
@Column(name = "publisher")
private String publisher;
@Column(name = "published_date")
private String publishedDate;
@Column(name = "isbn")
@Pattern(regexp = "^(?:ISBN(?:-1[03])?:? )?(?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$")
private String isbn;
@Column(name = "publisher")
private String publisher;
@Column(name = "published_date")
@Pattern(regexp = "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$")
private String publishedDate;

Comment on lines +69 to +72
implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.18.1'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.18.1'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.18.1'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.18.1'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Update Jackson dependencies from 2.18.1 to 2.18.2

The current version 2.18.1 is outdated. Version 2.18.2 is available with bug fixes and improvements. Update all Jackson dependencies to maintain version consistency:

  • com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.18.2
  • com.fasterxml.jackson.core:jackson-databind:2.18.2
  • com.fasterxml.jackson.core:jackson-annotations:2.18.2
  • com.fasterxml.jackson.core:jackson-core:2.18.2
🔗 Analysis chain

Update Jackson dependencies to latest stable version

The current version 2.18.1 is not the latest stable version. Consider updating to the latest version for security patches and improvements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check latest Jackson version from Maven Central
curl -s https://search.maven.org/solrsearch/select\?q\=g:%22com.fasterxml.jackson.core%22+AND+a:%22jackson-core%22\&rows\=1\&wt\=json | jq -r '.response.docs[0].latestVersion'

Length of output: 180

@becooq81 becooq81 closed this Dec 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: 도서 기능을 개발합니다
2 participants