Skip to content

Jan elia 24/exercise8#209

Open
jan-elia-24 wants to merge 16 commits intomainfrom
jan-elia-24/exercise8
Open

Jan elia 24/exercise8#209
jan-elia-24 wants to merge 16 commits intomainfrom
jan-elia-24/exercise8

Conversation

@jan-elia-24
Copy link
Copy Markdown

@jan-elia-24 jan-elia-24 commented Nov 19, 2025

Lab: Spring Boot REST API with JPA, MySQL 9+, and Thymeleaf

Implemented Features

  • Spring Boot 3.5.7 with Java 25
  • REST API with Book entity (GET, POST, DELETE endpoints)
  • Spring Data JPA with MySQL 9 database
  • Docker Compose for MySQL setup
  • Spring Security with Basic Authentication
  • Flyway database migrations
  • Unit tests for REST endpoints and security
  • Thymeleaf HTML view for displaying books

Testing

  • REST controller tests with MockMvc
  • Security access control tests (authenticated vs unauthenticated)
  • All tests passing ✅

How to Run

  1. Start Docker Desktop
  2. Run Exercise2025Application
  3. API available at: http://localhost:8080/api/books (requires auth: user/password)
  4. HTML view at: http://localhost:8080/books

Entity

Simple Book entity with:

  • id, title, author, year

Summary by CodeRabbit

Release Notes

  • New Features

    • Added book management REST API with full CRUD operations.
    • Added web interface for browsing the library collection.
    • Implemented basic authentication for API security.
  • Infrastructure

    • Added Docker Compose configuration for MySQL database setup.
    • Configured automated database migrations.
    • Upgraded to Spring Boot 3.5.7 and Java 25.
  • Tests

    • Added comprehensive test coverage for API endpoints and authentication.
    • Removed legacy placeholder tests.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 19, 2025

Warning

Rate limit exceeded

@jan-elia-24 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 10 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ba02555 and 9c1ae3b.

📒 Files selected for processing (1)
  • src/main/java/org/example/Exercise2025Application.java (1 hunks)

Walkthrough

This pull request transforms a basic Java project into a Spring Boot application with MySQL integration. It adds Docker Compose configuration, restructures pom.xml for Spring Boot 3.5.7, replaces the legacy entry point with Exercise2025Application, introduces a complete book management system with REST and MVC endpoints, adds Spring Security configuration, includes Flyway database migrations, and replaces old unit tests with Spring Boot integration tests.

Changes

Cohort / File(s) Summary
Project Configuration
docker-compose.yml, pom.xml
Added Docker Compose service for MySQL 9 with volume persistence. Converted pom.xml to use Spring Boot 3.5.7 parent, updated project coordinates (artifactId to exercise2025, version to 0.0.1-SNAPSHOT), added Java 25 configuration, replaced legacy test dependencies with Spring Boot starters (web, test, thymeleaf, data-jpa), added Flyway and MySQL connector dependencies, and consolidated build plugins to use spring-boot-maven-plugin.
Application Bootstrap
src/main/java/org/example/Exercise2025Application.java, src/main/java/org/example/App.java
Deleted legacy App.java with basic main method. Added new Exercise2025Application class annotated with @SpringBootApplication as the Spring Boot entry point.
Security Configuration
src/main/java/org/example/config/SecurityConfig.java
Introduced SecurityConfig class with SecurityFilterChain bean disabling CSRF, requiring authentication for /api/books/\*, allowing /books and other routes, enabling HTTP Basic auth. Added in-memory UserDetailsService with single user (username: user) and BCryptPasswordEncoder bean.
Data Layer
src/main/java/org/example/entity/Book.java, src/main/java/org/example/repository/BookRepository.java
Added Book JPA entity mapped to "books" table with id (auto-generated), title (NotBlank), author (NotBlank), and year fields. Added BookRepository interface extending JpaRepository<Book, Long>.
Service Layer
src/main/java/org/example/service/BookService.java
Introduced BookService with constructor-injected BookRepository providing CRUD operations: getAllBooks(), getBookById(Long), saveBook(Book), deleteBook(Long).
Web Layer
src/main/java/org/example/controller/BookController.java, src/main/java/org/example/controller/BookViewController.java
Added BookController REST endpoints under /api/books with GET all, GET by id (returns 404 if not found), POST create (returns 201), and DELETE. Added BookViewController MVC controller handling GET /books, populating model with books list and returning "books" view.
Database & Templates
src/main/resources/application.properties, src/main/resources/db/migration/V1__create_books_table.sql, src/main/resources/templates/books.html
Added application.properties configuring app name (exercise2025), MySQL datasource (localhost:3306/springlab), JPA/Hibernate with validate ddl-auto and SQL logging, and Flyway baseline-on-migrate. Added Flyway migration creating books table with BIGINT id, VARCHAR(255) title/author, and INT year. Added Thymeleaf template books.html rendering a styled table iterating over books collection with Thymeleaf expressions.
Test Suite
src/test/java/org/example/Exercise2025ApplicationTest.java, src/test/java/org/example/controller/BookControllerTest.java, src/test/java/org/example/AppIT.java, src/test/java/org/example/AppTest.java
Replaced legacy AppIT.java and AppTest.java tests. Added Exercise2025ApplicationTest with @SpringBootTest and contextLoads() sanity check. Added BookControllerTest using @WebMvcTest with mocked BookService, testing getAllBooks (200 OK), getBookById (200 OK, 404 Not Found), createBook (201 Created with CSRF), and unauthenticated access (401 Unauthorized).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant MVC as BookViewController
    participant Service as BookService
    participant Repository as BookRepository
    participant DB as MySQL
    participant Template as Thymeleaf

    User->>MVC: GET /books
    MVC->>Service: getAllBooks()
    Service->>Repository: findAll()
    Repository->>DB: SELECT * FROM books
    DB-->>Repository: Book[]
    Repository-->>Service: List<Book>
    Service-->>MVC: List<Book>
    MVC->>MVC: model.addAttribute("books", books)
    MVC->>Template: render books.html
    Template-->>User: HTML table with books
Loading
sequenceDiagram
    actor Client
    participant Security as SecurityConfig
    participant Controller as BookController
    participant Service as BookService
    participant Repository as BookRepository
    participant DB as MySQL

    Client->>Security: GET /api/books
    alt Authenticated
        Security->>Controller: request authorized
        Controller->>Service: getAllBooks()
        Service->>Repository: findAll()
        Repository->>DB: SELECT * FROM books
        DB-->>Repository: Book[]
        Repository-->>Service: List<Book>
        Service-->>Controller: List<Book>
        Controller-->>Client: 200 OK [Book, ...]
    else Not Authenticated
        Security-->>Client: 401 Unauthorized
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • SecurityConfig.java: Review authentication/authorization logic, CSRF disable justification, and in-memory user store appropriateness for production use
  • BookController.java: Verify HTTP status code mappings (404 handling for getBookById) and error response handling consistency
  • Exercise2025Application.java: Non-standard main method signature (void instead of public static void) requires verification that this works with Spring Boot launcher
  • pom.xml: Validate Spring Boot version compatibility, dependency versions, and plugin configuration; verify Java 25 support
  • BookControllerTest.java: Ensure test coverage adequacy for edge cases, CSRF token handling in tests, and authentication mocking strategy
  • Database migration and connection properties: Verify datasource URL, credentials management approach, and Flyway baseline strategy
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jan-elia-24/exercise8

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jan-elia-24 jan-elia-24 linked an issue Nov 19, 2025 that may be closed by this pull request
Copy link
Copy Markdown

@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: 1

🧹 Nitpick comments (4)
src/main/resources/db/migration/V1__create_books_table.sql (1)

1-6: Migration DDL matches the described Book model

Table definition is straightforward and consistent with the Book fields; Flyway should apply this cleanly. If you later decide year must always be present, you can tighten it with NOT NULL, but current design is fine for this exercise.

src/main/java/org/example/config/SecurityConfig.java (1)

15-47: Security config aligns with the lab goals; keep CSRF in mind if you add forms

The filter chain cleanly protects /api/books/** with HTTP Basic while leaving /books and other routes open, and the in‑memory user/password setup is appropriate for a learning exercise (hard‑coded test creds are expected here). If you later introduce state‑changing operations from HTML forms (beyond pure REST clients), consider re‑enabling CSRF protection or scoping its disablement to API endpoints only. Based on learnings

src/main/resources/application.properties (1)

1-16: Datasource/JPA/Flyway settings are coherent with the Docker MySQL setup

URL, database name, and credentials line up with docker-compose.yml, and using ddl-auto=validate alongside Flyway is a solid choice. For a production‑style setup you’d typically move the credentials to environment variables or profile‑specific configs, but for this training project the hard‑coded values are acceptable. Based on learnings

src/test/java/org/example/controller/BookControllerTest.java (1)

1-71: Good controller coverage; consider adding delete/404 tests

The tests nicely cover basic success paths and the unauthorized access case. To round this out, consider adding:

  • A test for GET /api/books/{id} returning 404 when the service returns empty.
  • A test for DELETE /api/books/{id} to verify the status code for successful deletion (and optionally for a non-existing id if you change the controller behavior accordingly).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8618163 and ba02555.

📒 Files selected for processing (17)
  • docker-compose.yml (1 hunks)
  • pom.xml (1 hunks)
  • src/main/java/org/example/App.java (0 hunks)
  • src/main/java/org/example/Exercise2025Application.java (1 hunks)
  • src/main/java/org/example/config/SecurityConfig.java (1 hunks)
  • src/main/java/org/example/controller/BookController.java (1 hunks)
  • src/main/java/org/example/controller/BookViewController.java (1 hunks)
  • src/main/java/org/example/entity/Book.java (1 hunks)
  • src/main/java/org/example/repository/BookRepository.java (1 hunks)
  • src/main/java/org/example/service/BookService.java (1 hunks)
  • src/main/resources/application.properties (1 hunks)
  • src/main/resources/db/migration/V1__create_books_table.sql (1 hunks)
  • src/main/resources/templates/books.html (1 hunks)
  • src/test/java/org/example/AppIT.java (0 hunks)
  • src/test/java/org/example/AppTest.java (0 hunks)
  • src/test/java/org/example/Exercise2025ApplicationTest.java (1 hunks)
  • src/test/java/org/example/controller/BookControllerTest.java (1 hunks)
💤 Files with no reviewable changes (3)
  • src/test/java/org/example/AppTest.java
  • src/main/java/org/example/App.java
  • src/test/java/org/example/AppIT.java
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: jennymakki
Repo: fungover/exercise2025 PR: 204
File: src/main/java/org/example/config/SecurityConfig.java:19-24
Timestamp: 2025-11-16T13:56:11.263Z
Learning: The repository fungover/exercise2025 is an exercise/learning project where hard-coded credentials and other shortcuts for ease of testing are acceptable and intentional.
📚 Learning: 2025-11-16T13:56:11.263Z
Learnt from: jennymakki
Repo: fungover/exercise2025 PR: 204
File: src/main/java/org/example/config/SecurityConfig.java:19-24
Timestamp: 2025-11-16T13:56:11.263Z
Learning: The repository fungover/exercise2025 is an exercise/learning project where hard-coded credentials and other shortcuts for ease of testing are acceptable and intentional.

Applied to files:

  • src/main/resources/application.properties
  • pom.xml
  • src/test/java/org/example/Exercise2025ApplicationTest.java
  • src/main/java/org/example/Exercise2025Application.java
📚 Learning: 2025-09-10T14:02:54.365Z
Learnt from: alfredbrannare
Repo: fungover/exercise2025 PR: 66
File: src/test/java/org/example/service/WarehouseTest.java:1-21
Timestamp: 2025-09-10T14:02:54.365Z
Learning: In the fungover/exercise2025 project, static mocking of LocalDateTime.now() works successfully with the existing Mockito setup without requiring mockito-inline dependency.

Applied to files:

  • src/test/java/org/example/Exercise2025ApplicationTest.java
🔇 Additional comments (14)
docker-compose.yml (1)

1-15: MySQL compose setup is consistent with the app config

Service name, database name, credentials, port mapping, and volume declaration all line up with the datasource settings in application.properties, so this should work smoothly for local development.

src/main/java/org/example/repository/BookRepository.java (1)

1-9: Standard Spring Data JPA repository definition looks good

Extending JpaRepository<Book, Long> is the correct, idiomatic setup here. Just make sure the Book entity’s @Id property is actually a Long so the generic type parameters stay consistent.

src/main/resources/templates/books.html (1)

1-34: Template structure and bindings look consistent

The table markup and th:each/th:text bindings align with the Book fields and the books model attribute; no issues spotted.

src/test/java/org/example/Exercise2025ApplicationTest.java (1)

1-13: Context load smoke test is fine

Simple @SpringBootTest with contextLoads() is sufficient to verify the application context starts.

src/main/java/org/example/controller/BookViewController.java (1)

1-22: View controller wiring matches template and service

The /books handler correctly delegates to bookService.getAllBooks() and exposes the result as books, matching templates/books.html; implementation looks good.

src/main/java/org/example/service/BookService.java (1)

1-34: Service layer passthrough looks correct

The service cleanly delegates CRUD operations to BookRepository with appropriate method signatures; no issues detected.

src/main/java/org/example/entity/Book.java (1)

1-43: Entity definition is consistent and complete

The Book entity fields, constructors, and accessors are coherent with the rest of the codebase, and annotations align with the expected books table structure.

src/main/java/org/example/controller/BookController.java (1)

21-43: Add @Valid for request body validation; remove deleteBook suggestion

One actionable suggestion, one concern to clarify:

  1. Trigger bean validation on create

You have @NotBlank on Book fields; add @Valid to trigger validation on invalid payloads:

@PostMapping
public ResponseEntity<Book> createBook(@jakarta.validation.Valid @RequestBody Book book) {
    Book saved = bookService.saveBook(book);
    return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}

(Alternatively, add import jakarta.validation.Valid; and use @Valid.)

  1. deleteBook behavior note

The original suggestion to check existence before delete is unnecessary: Spring Data JPA's deleteById(id) (used in your service) does not throw for missing ids in Spring Boot 3.5.7+. It silently succeeds, so returning 204 is safe. If you want to return 404 for a missing book, that is a design choice, not a bug fix.

Likely an incorrect or invalid review comment.

pom.xml (6)

5-10: Clean Spring Boot parent POM inheritance.

Well-structured parent POM setup with proper relative path configuration. The Spring Boot BOM approach will centralize dependency management for most of your ecosystem.


63-65: Verify spring-boot-docker-compose runtime scope.

The Docker Compose support is scoped to runtime, which is appropriate for development/local testing. Confirm this won't be packaged into production builds, or adjust if needed for your deployment pipeline.


16-28: Empty metadata elements are acceptable for an exercise project.

Metadata like <url>, <license>, <developers>, and <scm> are left empty. While typically these would be populated in a real project, this is fine for an exercise/learning repository. Based on learnings


87-92: Proper spring-boot-maven-plugin configuration.

The plugin is correctly configured with the main entry point class (org.example.Exercise2025Application). This ensures fat JAR packaging and proper executable support.


48-82: Both dependencies are properly managed by Spring Boot 3.5.7 BOM—no action needed.

The Spring Boot 3.5.7 BOM includes both flyway-mysql and spring-security-test in its managed dependencies, so omitting explicit <version> tags is correct and follows the intended BOM pattern. The dependencies on lines 71-72 and 79-80 are properly declared.

Likely an incorrect or invalid review comment.


30-31: Test Flyway on Java 25 before deploying to production.

Verification confirms Spring Boot 3.5.7 officially supports Java 25, and MySQL Connector/J is compatible with Java 25+. However, Flyway does not list Java 25 as officially supported and Java 24 is known to emit warnings.

Thoroughly test Flyway's behavior in your environment with Java 25, or consider using a Java LTS version (17 or 21) for production stability.

Comment thread src/main/java/org/example/Exercise2025Application.java
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.

Exercise 8 - Spring Boot

2 participants