Skip to content

feature/options#5

Closed
LinusWestling wants to merge 10 commits intomainfrom
feature/options
Closed

feature/options#5
LinusWestling wants to merge 10 commits intomainfrom
feature/options

Conversation

@LinusWestling
Copy link
Copy Markdown

@LinusWestling LinusWestling commented Dec 18, 2025

Summary by CodeRabbit

  • New Features

    • Interactive CLI login with distinct admin and user workflows; richer input validation and user prompts
    • Admin UI to create/delete users, movies, actors, directors, genres and manage relations
    • Enhanced movie discovery filters (language, release date, length, ranking, cast, genre, title)
    • Movie rating and personalized favorites; seeded Admin user and automated initial data seeding
  • Tests

    • Expanded integration tests using an in-memory database
  • Chores

    • Build/test configuration updates and README checklist status updated

✏️ Tip: You can customize this high-level summary in your review settings.

Linus Westling and others added 6 commits December 18, 2025 09:07
Basic tests also implmented.

Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>

Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>

Co-authored-by: Mark Cavric <cavric_123@hotmail.se>

Co-authored-by: Linus Westling <westling.linus@gmail.com>
Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>

Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>

Co-authored-by: Mark Cavric <cavric_123@hotmail.se>

Co-authored-by: Linus Westling <westling.linus@gmail.com>
…ontiued implementation of switch menue's.

Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>

Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>

Co-authored-by: Mark Cavric <cavric_123@hotmail.se>

Co-authored-by: Linus Westling <westling.linus@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Dec 18, 2025

Walkthrough

Bootstraps runtime JPA seeding with a DB-empty check, adds JPA utilities and a transaction runner, introduces interactive CLI (user + admin), extends repository APIs and implementations (queries and signatures), updates seed data/tests, and adds H2 test dependency plus Surefire config.

Changes

Cohort / File(s) Summary
Build & Docs
pom.xml, NOTES.md, README.md
Added H2 test dependency and Maven Surefire config; inserted extensive domain/use-case notes in NOTES.md; toggled a checklist item in README.md.
App bootstrap & seeding
src/main/java/org/example/App.java, src/main/java/org/example/DatabaseFiller.java
App now checks DB emptiness at runtime and calls DatabaseFiller.seedAll() when empty; added isDatabaseEmpty(EntityManager) and seedAll() orchestration; reworked CLI login flow and entry points.
JPA utilities & transaction helper
src/main/java/org/example/JpaUtil.java, src/main/java/org/example/JpaRunner.java
Added JpaUtil with static EMF init, getEntityManager()/close(); added JpaRunner.runInTransaction(Consumer<EntityManager>) for managed transactions.
CLI applications
src/main/java/org/example/CliApp.java, src/main/java/org/example/CliAdminApp.java
New interactive CLI classes: CliApp for regular users (menus for favorites, search, ratings) and CliAdminApp for admin CRUD operations (users, movies, actors, directors, genres).
Repository implementations
src/main/java/org/example/jpaimpl/MovieRepoJpa.java, .../ActorRepoJpa.java, .../DirectorRepoJpa.java, .../UserRatingRepoJpa.java
MovieRepoJpa now implements MovieRepo and adds many query APIs (by genre, date, length, ranking, language, director, actor, getAll, getById); ActorRepoJpa/DirectorRepoJpa added deleteByName(String); UserRatingRepoJpa changed rating types to double and rateMovie now returns boolean.
Repository interfaces
src/main/java/org/example/repo/MovieRepo.java, src/main/java/org/example/repo/UserRatingRepo.java
Removed several actor/director setter methods from MovieRepo; added getMovieByGenre(String); updated UserRatingRepo to use double for ratings and make rateMovie return boolean.
Seeders
src/main/java/org/example/seed/SeedMovies.java, .../SeedMovieRelations.java, .../SeedUsers.java
Removed em.clear() from SeedMovies batch loop; minor whitespace cleanup in SeedMovieRelations; added an Admin user entry in SeedUsers.
Tests
src/test/java/org/example/AppTest.java
Replaced placeholder test with H2-backed integration-style tests: EMF lifecycle, seeder tests, repository integration, relation checks, and a user-menu flow test (Mockito).
POJO change
src/main/java/org/example/pojo/UserRating.java
Constructor and setter signatures switched from float to double for rating parameter types.

Sequence Diagram(s)

sequenceDiagram
  participant User as CLI User
  participant App as App.main
  participant JpaR as JpaRunner
  participant EM as EntityManager / DB
  participant Seeder as DatabaseFiller
  participant Repo as Repositories

  User->>App: start
  App->>JpaR: runInTransaction(isDatabaseEmpty)
  JpaR->>EM: obtain EM, begin tx
  EM->>Repo: count Movies
  Repo-->>EM: result
  EM-->>JpaR: commit
  JpaR-->>App: returns empty? 
  alt DB empty
    App->>JpaR: runInTransaction(seedAll)
    JpaR->>EM: begin tx
    Seeder->>Repo: persist genres, actors, directors, movies, users, relations
    Repo-->>EM: persist ops
    EM-->>JpaR: commit
    JpaR-->>App: seed completed
  end
  App->>User: prompt login
  User->>App: credentials
  App->>JpaR: runInTransaction(findUser)
  JpaR->>EM: query user
  EM-->>JpaR: user result
  JpaR-->>App: user (or none)
  alt admin
    App->>User: dispatch to CliAdminApp (interactive transactions)
  else normal user
    App->>User: dispatch to CliApp (menus & repo queries)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Pay extra attention to:
    • JpaUtil static initialization and registered entity list.
    • Transaction semantics and exception handling in JpaRunner.
    • MovieRepoJpa JPQL queries, date parsing, and range/filter validations.
    • API surface/type changes around ratings (float→double) across repos, POJO, and callers.
    • CLI classes for correct transaction boundaries and input validation.

Possibly related PRs

Poem

🐰
I hopped through tables, seeds in tow,
Began the DB with a gentle glow.
Transactions snug, the CLI sings,
New users, genres — tiny springs.
Carrots for commits and tests that grow 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'feature/options' is a branch naming convention rather than a meaningful description of the changeset's content. Replace with a descriptive title summarizing the main changes, such as 'Add CLI interface and refactor application entry point' or 'Implement user and admin menu systems with JPA integration.'
Docstring Coverage ⚠️ Warning Docstring coverage is 12.20% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 feature/options

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.

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: 18

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (4)
src/main/java/org/example/jpaimpl/DirectorRepoJpa.java-49-62 (1)

49-62: Fix copy-paste errors in comments.

The comments at lines 57 and 61 incorrectly refer to "actor" instead of "director".

🔎 Apply this diff to correct the comments:
     if (director == null) {
-        return false; // ingen actor hittades
+        return false; // ingen director hittades
     }
 
     em.remove(director);
-    return true; // actor togs bort
+    return true; // director togs bort
 }
src/test/java/org/example/AppTest.java-236-237 (1)

236-237: Pass actual user ID instead of null.

Line 237 calls app.optionsUser(userRepoMock, movieRepoMock, null) with null for the User parameter, but the test setup doesn't show what user should be passed. This could cause issues if optionsUser expects a non-null user.

src/main/java/org/example/CliApp.java-331-331 (1)

331-331: Display rating result to user.

Line 331 calls getRatingForMovieByUser but doesn't capture or display the result. The user won't see their rating.

🔎 Suggested fix:
-                        movieOpt.ifPresent(movie -> userRatingRepoJpa.getRatingForMovieByUser(user, movie));
+                        movieOpt.ifPresent(movie -> {
+                            Optional<Float> rating = userRatingRepoJpa.getRatingForMovieByUser(user, movie);
+                            if (rating.isPresent()) {
+                                System.out.println("Your rating for '" + movie.getTitle() + "': " + rating.get());
+                            } else {
+                                System.out.println("You haven't rated '" + movie.getTitle() + "' yet.");
+                            }
+                        });
src/main/java/org/example/CliApp.java-220-221 (1)

220-221: Unused Genre entity creation.

A new Genre entity is created but never used. The method call on line 223 uses genreName (String) directly, not the created Genre object.

Consider removing the unused entity creation:

                 System.out.println("***** You have selected find a movie by genre *****");
                 System.out.println("Enter Genre: ");
                 String genreName = sc.nextLine();

-                Genre genre = new Genre();
-                genre.setName(genreName);
-
                 List<Movie> moviesByGenre = movieRepoJpa.getMovieByGenre(genreName);

                 if (moviesByGenre.isEmpty()) {
-                    System.out.println("No movies found in genre: " + genre.getName());
+                    System.out.println("No movies found in genre: " + genreName);
🧹 Nitpick comments (7)
src/main/java/org/example/jpaimpl/DirectorRepoJpa.java (1)

5-5: Remove unused import.

The Actor import is not used in this file.

🔎 Apply this diff to remove the unused import:
-import org.example.pojo.Actor;
 import org.example.pojo.Director;
src/main/java/org/example/DatabaseFiller.java (1)

23-27: Consider checking multiple tables in isDatabaseEmpty.

Currently, isDatabaseEmpty only checks the Movie table. If other tables (User, Actor, Director, Genre) contain data while Movie is empty, re-seeding could cause issues. While this might work given the current seeding strategy, it's fragile and could break if the seeding logic changes.

🔎 Consider this more robust implementation:
 public static boolean isDatabaseEmpty(EntityManager em) {
     Long movieCount = em.createQuery("SELECT COUNT(m) FROM Movie m", Long.class)
         .getSingleResult();
-    return movieCount == 0;
+    Long userCount = em.createQuery("SELECT COUNT(u) FROM User u", Long.class)
+        .getSingleResult();
+    return movieCount == 0 && userCount == 0;
 }
src/test/java/org/example/AppTest.java (1)

32-39: Consider extracting persistence configuration to a helper method.

The inline Map configuration in the test setup is verbose and could be reused. Consider extracting it to a test utility method for better maintainability.

src/main/java/org/example/CliAdminApp.java (1)

51-240: Consider extracting transaction management to reduce duplication.

Each case block manually manages transactions with repetitive begin() and commit() calls. Consider using the JpaRunner.runInTransaction utility introduced in this PR to reduce duplication.

src/main/java/org/example/CliApp.java (2)

296-296: Consider checking rateMovie return value.

The rateMovie method now returns a boolean to indicate success/failure, but the return value is ignored here. Consider checking it to provide user feedback.


24-109: Consider extracting menu loop pattern.

The menu handling pattern (print options, loop with switch, handle exit) is repeated in all three option methods. Consider extracting this to a helper method to reduce duplication.

src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)

186-197: Add @OverRide annotation for consistency.

The getMovieByGenre method appears to implement an interface method (per the AI summary), but is missing the @Override annotation unlike other interface methods in this class.

+@Override
 public List<Movie> getMovieByGenre (String genre) {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a48098b and d21efa9.

📒 Files selected for processing (19)
  • NOTES.md (1 hunks)
  • README.md (1 hunks)
  • pom.xml (1 hunks)
  • src/main/java/org/example/App.java (1 hunks)
  • src/main/java/org/example/CliAdminApp.java (1 hunks)
  • src/main/java/org/example/CliApp.java (1 hunks)
  • src/main/java/org/example/DatabaseFiller.java (2 hunks)
  • src/main/java/org/example/JpaRunner.java (1 hunks)
  • src/main/java/org/example/JpaUtil.java (1 hunks)
  • src/main/java/org/example/jpaimpl/ActorRepoJpa.java (1 hunks)
  • src/main/java/org/example/jpaimpl/DirectorRepoJpa.java (2 hunks)
  • src/main/java/org/example/jpaimpl/MovieRepoJpa.java (5 hunks)
  • src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java (2 hunks)
  • src/main/java/org/example/repo/MovieRepo.java (1 hunks)
  • src/main/java/org/example/repo/UserRatingRepo.java (1 hunks)
  • src/main/java/org/example/seed/SeedMovieRelations.java (0 hunks)
  • src/main/java/org/example/seed/SeedMovies.java (0 hunks)
  • src/main/java/org/example/seed/SeedUsers.java (1 hunks)
  • src/test/java/org/example/AppTest.java (1 hunks)
💤 Files with no reviewable changes (2)
  • src/main/java/org/example/seed/SeedMovies.java
  • src/main/java/org/example/seed/SeedMovieRelations.java
🧰 Additional context used
🧬 Code graph analysis (4)
src/main/java/org/example/CliAdminApp.java (1)
src/main/java/org/example/seed/SeedUsers.java (1)
  • SeedUsers (9-153)
src/main/java/org/example/CliApp.java (3)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)
  • MovieRepoJpa (20-224)
src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java (1)
  • UserRatingRepoJpa (12-124)
src/main/java/org/example/jpaimpl/UserRepoJpa.java (1)
  • UserRepoJpa (13-135)
src/main/java/org/example/JpaRunner.java (1)
src/main/java/org/example/JpaUtil.java (1)
  • JpaUtil (9-34)
src/test/java/org/example/AppTest.java (2)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)
  • MovieRepoJpa (20-224)
src/main/java/org/example/jpaimpl/UserRepoJpa.java (1)
  • UserRepoJpa (13-135)
🪛 GitHub Actions: Java Maven Build
pom.xml

[error] 1-1: Maven Surefire test run failed. 10 errors detected during tests; build failed.

src/test/java/org/example/AppTest.java

[error] 44-44: NullPointerException: emf is null in setup(AppTest.java:44) when trying to create EntityManager from EntityManagerFactory.


[error] 49-49: NullPointerException: emf is null in tearDown(AppTest.java:49) when attempting to close EntityManager.


[error] 54-54: NullPointerException: emf is null in closeFactory(AppTest.java:54) when attempting to close EntityManagerFactory.

🔇 Additional comments (16)
pom.xml (1)

53-58: LGTM! H2 test dependency added appropriately.

The H2 in-memory database dependency is correctly scoped for testing and supports the integration test suite.

NOTES.md (1)

87-129: LGTM! Clear documentation of domain model and use cases.

The added documentation provides a comprehensive overview of the entities and their operations, which will help with understanding the system design.

README.md (1)

23-23: LGTM! Progress tracking updated.

The checkbox update accurately reflects the completion of documenting design decisions.

src/main/java/org/example/DatabaseFiller.java (1)

29-54: LGTM! Well-structured seeding orchestration.

The seedAll method follows a logical progression: base entities first, then relations. This separation of concerns makes the seeding process clear and maintainable.

src/main/java/org/example/JpaRunner.java (1)

11-22: LGTM: Transaction lifecycle is correctly managed.

The transaction handling follows best practices: begins transaction, executes action, commits on success, rolls back on exception when active, and ensures EntityManager is closed in the finally block.

src/main/java/org/example/repo/MovieRepo.java (1)

28-28: LGTM: Genre-based query method added.

The new getMovieByGenre method provides a useful query capability for filtering movies by genre.

src/main/java/org/example/JpaUtil.java (1)

27-29: LGTM: EntityManager lifecycle methods are clean.

The getEntityManager() and close() methods provide straightforward access to JPA resources.

src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java (1)

85-121: LGTM: Boolean return type improves API usability.

The change from void to boolean return type allows callers to detect success/failure. The null handling is now more graceful (returns false instead of throwing an exception), and the movie ranking recalculation logic is correct.

src/main/java/org/example/CliAdminApp.java (1)

47-48: LGTM: Input handling is correct here.

The nextInt() followed by nextLine() pattern correctly consumes the newline character.

src/main/java/org/example/App.java (1)

21-27: LGTM: Database seeding with empty check is well-designed.

The conditional seeding approach prevents duplicate data and provides a helpful message when the database is already populated.

src/main/java/org/example/jpaimpl/MovieRepoJpa.java (6)

20-26: LGTM! Repository pattern correctly implemented.

The class properly implements the MovieRepo interface and follows standard dependency injection with EntityManager.


97-107: LGTM! Better exception handling with stream API.

The refactoring from getSingleResult() to getResultStream().findFirst() properly avoids NoResultException and provides cleaner Optional handling.


130-139: LGTM! Query logic is correct.

The length validation and query implementation are appropriate.


154-165: LGTM! Language query is correctly implemented.

The null check and query logic are appropriate.


167-184: LGTM! Standard query implementations.

Both getAllMovies() and getById() follow JPA best practices.


172-179: This is a pure JPA application using resource-local transactions, not a Spring application.

The methods deleteMovie, setDirector, addActors, and addGenres perform persistence operations (em.remove(), em.merge()) and are correctly used within transaction contexts. All current callers in CliAdminApp and DatabaseFiller explicitly wrap these method calls with em.getTransaction().begin() and em.getTransaction().commit(), ensuring changes are persisted.

However, the current design relies on caller responsibility to manage transactions. Consider either (1) documenting this transaction requirement clearly in method javadocs, or (2) wrapping these methods with a helper similar to JpaRunner.runInTranscation() to enforce transaction boundaries at the method level.

Likely an incorrect or invalid review comment.

Comment on lines +15 to +17
.jdbcUrl("jdbc:mysql://localhost:3306/codeTraumaTeam")
.jdbcUsername("user")
.jdbcPassword("password")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Externalize database credentials immediately.

Database credentials are hard-coded in source code, exposing them in version control. This is a critical security vulnerability that could lead to unauthorized database access.

🔎 Recommended approach:

Store credentials in environment variables or a configuration file outside version control:

-            .jdbcUrl("jdbc:mysql://localhost:3306/codeTraumaTeam")
-            .jdbcUsername("user")
-            .jdbcPassword("password")
+            .jdbcUrl(System.getenv("DB_URL"))
+            .jdbcUsername(System.getenv("DB_USERNAME"))
+            .jdbcPassword(System.getenv("DB_PASSWORD"))

Add a .env file to .gitignore and document the required environment variables in the README.

📝 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
.jdbcUrl("jdbc:mysql://localhost:3306/codeTraumaTeam")
.jdbcUsername("user")
.jdbcPassword("password")
.jdbcUrl(System.getenv("DB_URL"))
.jdbcUsername(System.getenv("DB_USERNAME"))
.jdbcPassword(System.getenv("DB_PASSWORD"))
🤖 Prompt for AI Agents
In src/main/java/org/example/JpaUtil.java around lines 15 to 17, the database
URL, username and password are hard-coded which leaks credentials; change the
code to read these values from environment variables or an external config
(e.g., System.getenv or a properties file loaded from outside version control),
add instructions to document required env vars in the README, and ensure any
.env or config file is added to .gitignore so secrets are never committed.

Optional<Double> getAverageRatingForMovie(Movie movie);

void rateMovie(User user, Movie movie, float rating);
boolean rateMovie(User user, Movie movie, float rating);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find the UserRatingRepo interface definition
echo "=== Interface Definition ==="
find . -type f -name "*.java" | xargs grep -l "interface UserRatingRepo" 2>/dev/null

# Find the interface file and show its content
echo -e "\n=== UserRatingRepo Interface ==="
find . -type f -name "UserRatingRepo.java" | head -1 | xargs cat -n

# Find all implementations of UserRatingRepo
echo -e "\n=== Implementations of UserRatingRepo ==="
rg -nP --type=java "implements.*UserRatingRepo|class \w+ implements" -A 20

# Find all call sites of rateMovie
echo -e "\n=== Call sites of rateMovie ==="
rg -nP --type=java "\.rateMovie\s*\(" -B 2 -A 3

# Find method implementations within classes
echo -e "\n=== rateMovie implementations ==="
ast-grep --pattern $'rateMovie($$$) {
  $$$
}'

Repository: ithsjava25/project-jpa-grupp-5-d

Length of output: 13193


🏁 Script executed:

#!/bin/bash

# Show the complete UserRatingRepoJpa file to find rateMovie implementation
echo "=== UserRatingRepoJpa full content ==="
cat -n src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java

# Also search for the rateMovie method specifically
echo -e "\n=== rateMovie method in detail ==="
rg -nP --type=java -A 15 "public.*rateMovie" src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java

Repository: ithsjava25/project-jpa-grupp-5-d

Length of output: 5413


Update call sites to handle the boolean return value.

The interface and implementation correctly return boolean, but call sites ignore the return value:

  • CliApp.java:296 prints success unconditionally without checking the result
  • SeedUserRelations.java:38 discards the return value without error handling

Update both call sites to check the return value and handle failure cases (e.g., when user or movie is null).

🤖 Prompt for AI Agents
In src/main/java/org/example/repo/UserRatingRepo.java around line 15 and at the
call sites src/main/java/org/example/cli/CliApp.java line ~296 and
src/main/java/org/example/seed/SeedUserRelations.java line ~38, the rateMovie
method returns boolean but callers ignore it; update both call sites to check
the returned boolean and handle failures: after calling rateMovie, if it returns
true proceed with the success flow, if false log/report an error (e.g., print a
failure message, return an error code, or throw a controlled exception), and
optionally pre-check for null user or movie before calling to give a clearer
error message. Ensure CliApp only prints success when rateMovie returns true,
and SeedUserRelations handles false by logging or retrying as appropriate.

UserRepoJpa userRepo = new UserRepoJpa(em);
Map<String, User> users = new HashMap<>();

users.put("Admin", userRepo.addUser("Admin", "Admin"));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Security concern: Weak hardcoded Admin credentials.

The Admin user is created with the password "Admin", which is extremely weak and predictable. While this may be acceptable for development seeding, it poses a security risk if this code is ever used in a production environment.

Consider one of these approaches:

  1. Use environment variables for admin credentials:
String adminPassword = System.getenv("ADMIN_PASSWORD");
if (adminPassword == null || adminPassword.isEmpty()) {
    adminPassword = "Admin"; // fallback for dev/test only
}
users.put("Admin", userRepo.addUser("Admin", adminPassword));
  1. At minimum, add a warning comment:
// WARNING: This is test data only. Never use these credentials in production!
users.put("Admin", userRepo.addUser("Admin", "Admin"));
  1. Consider not seeding admin users and instead requiring admins to be created through a secure setup process.
🤖 Prompt for AI Agents
In src/main/java/org/example/seed/SeedUsers.java around line 21, the Admin user
is created with a weak hardcoded password "Admin"; replace this with a secure
approach: read the admin password from an environment variable (with a clear
dev-only fallback) or remove seeding of admin accounts entirely, and if you must
keep a hardcoded value add an explicit warning comment and ensure the repository
never ships that value to production; implement the env-var read and fallback
logic, or remove the seed and document the secure admin creation process in
deployment notes.

Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>
Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>
Co-authored-by: Mark Cavric <cavric_123@hotmail.se>
Co-authored-by: Linus Westling <westling.linus@gmail.com>
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: 2

♻️ Duplicate comments (1)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)

109-117: Stub implementations still return empty lists.

These methods are called by CliApp but always return empty results, causing silent failures. This was flagged in a previous review and remains unimplemented.

🧹 Nitpick comments (1)
src/main/java/org/example/App.java (1)

63-67: Consider using a role field instead of hardcoded username check.

Checking user.getUserName().equals("Admin") is brittle—it's case-sensitive and ties admin detection to a specific username string. If the User entity has (or could have) an isAdmin flag or role field, use that instead for more robust authorization.

🔎 Suggested approach
-            if (user.getUserName().equals("Admin")) {
+            if (user.isAdmin()) {  // or user.getRole() == Role.ADMIN
                 new CliAdminApp(em).printOptions();
             } else {
                 new CliApp().runUserMenu(sc, userRepoJpa, userRatingRepoJpa, movieRepoJpa, user);
             }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d21efa9 and fc2e29e.

📒 Files selected for processing (4)
  • src/main/java/org/example/App.java (1 hunks)
  • src/main/java/org/example/CliApp.java (1 hunks)
  • src/main/java/org/example/JpaRunner.java (1 hunks)
  • src/main/java/org/example/jpaimpl/MovieRepoJpa.java (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/example/CliApp.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/org/example/JpaRunner.java (1)
src/main/java/org/example/JpaUtil.java (1)
  • JpaUtil (9-34)
🔇 Additional comments (5)
src/main/java/org/example/JpaRunner.java (1)

10-23: LGTM! Standard JPA transaction wrapper pattern.

The implementation correctly handles the transaction lifecycle: begin, execute action, commit on success, rollback on RuntimeException, and close the EntityManager in finally. The typo from the previous review has been fixed.

src/main/java/org/example/App.java (1)

31-57: Login flow implementation is correct.

The try-with-resources ensures the EntityManager is closed, and the retry loop with user confirmation provides good UX. The previous scope issues from past reviews have been addressed—optionalUser is now properly scoped and user is extracted after the loop.

src/main/java/org/example/jpaimpl/MovieRepoJpa.java (3)

97-107: LGTM! Clean implementation of findByTitle.

Properly validates input, uses stream to safely return first match as Optional, avoiding NoResultException handling.


175-178: LGTM! Query methods are correctly implemented.

getAllMovies(), getById(), and getMovieByGenre() follow proper JPA patterns with appropriate null checks and query structures.

Also applies to: 189-192, 194-205


138-160: LGTM! Length and ranking queries are properly implemented.

Both methods validate input bounds and construct correct JPQL queries with ordering.

Comment on lines +162 to +173
@Override
public List<Movie> getMovieByLanguage(Language language) {
if (language == null){
return List.of();
}

return em.createQuery(
"select m from Movie m where language = :language", Movie.class)
.setParameter("language", language)
.getResultList();

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add entity alias to the language field in the query.

The query uses language = :language but should use m.language = :language for consistency with other queries and to avoid potential ambiguity.

🔎 Proposed fix
         return em.createQuery(
-            "select m from Movie m where language = :language", Movie.class)
+            "select m from Movie m where m.language = :language", Movie.class)
             .setParameter("language", language)
             .getResultList();
📝 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
@Override
public List<Movie> getMovieByLanguage(Language language) {
if (language == null){
return List.of();
}
return em.createQuery(
"select m from Movie m where language = :language", Movie.class)
.setParameter("language", language)
.getResultList();
}
@Override
public List<Movie> getMovieByLanguage(Language language) {
if (language == null){
return List.of();
}
return em.createQuery(
"select m from Movie m where m.language = :language", Movie.class)
.setParameter("language", language)
.getResultList();
}
🤖 Prompt for AI Agents
In src/main/java/org/example/jpaimpl/MovieRepoJpa.java around lines 162 to 173,
the JPQL query uses an unqualified language field ("language = :language") which
can be ambiguous; update the query to use the entity alias by changing the
predicate to "m.language = :language" so it consistently references the Movie
alias, keep the rest of the query and parameter setting the same.

Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>
Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>
Co-authored-by: Mark Cavric <cavric_123@hotmail.se>
Co-authored-by: Linus Westling <westling.linus@gmail.com>
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: 7

♻️ Duplicate comments (2)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (2)

180-184: Add entity alias to the language field in the query.

The query uses language = :language but should use m.language = :language for consistency with other queries and to avoid potential ambiguity.


133-146: Handle potential DateTimeParseException from date parsing.

LocalDate.parse() with the custom formatter will throw DateTimeParseException if the input doesn't match the expected "yyyyMMdd" format.

🧹 Nitpick comments (8)
src/main/java/org/example/CliAdminApp.java (3)

66-77: Missing nextLine() after nextLong() may cause issues in subsequent cases.

After scan.nextLong() at line 68, the newline character remains in the buffer. While this case doesn't read another line immediately, if the user continues using the menu, input behavior could become inconsistent. Consider adding scan.nextLine() after line 68 for consistency with other cases.

🔎 Suggested fix
                 case 2 -> {
                     System.out.println("Enter userId to delete:");
                     long userId = scan.nextLong();
+                    scan.nextLine(); // consume newline

                     UserRepoJpa userRepo = new UserRepoJpa(em);

104-112: Missing nextLine() after nextLong().

Same issue as case 2 - after scan.nextLong() at line 106, the newline remains in the buffer.

🔎 Suggested fix
                 case 4 -> {
                     System.out.println("Enter movieId to delete:");
                     long movieId = scan.nextLong();
+                    scan.nextLine(); // consume newline
                     MovieRepoJpa movieRepo = new MovieRepoJpa(em);

37-37: Remove or translate Swedish comment in menu text.

The menu item contains "***** ta bort? enum?" which appears to be a development note in Swedish. This should be removed before release.

src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)

219-240: Silent failures when movie is not found.

The helper methods setDirector, addActors, and addGenres silently do nothing when the movie title is not found. Consider returning a boolean or throwing an exception to inform callers of failure, especially since these are used in CLI flows where user feedback is important.

🔎 Suggested approach
-    public void setDirector(String title, Director director) {
+    public boolean setDirector(String title, Director director) {
         Movie m = findByTitle(title).orElse(null);
         if (m != null) {
             m.setDirector(director);
             em.merge(m);
+            return true;
         }
+        return false;
     }

Apply similar changes to addActors and addGenres.

src/main/java/org/example/App.java (1)

65-66: Hardcoded admin username is fragile.

Checking for admin status via user.getUserName().equals("Admin") is case-sensitive and hardcoded. Consider using a role-based approach or at minimum case-insensitive comparison.

🔎 Suggested improvement
-            if (user.getUserName().equals("Admin")) {
+            if (user.getUserName().equalsIgnoreCase("Admin")) {
                 new CliAdminApp(em).printOptions();

Better long-term: Add an isAdmin() method or role field to the User entity.

src/main/java/org/example/CliApp.java (3)

378-378: Creating new Scanner instead of using passed Scanner.

The optionsUserRating method creates a new Scanner(System.in) at line 378 instead of accepting a Scanner parameter like other methods. This is inconsistent and could cause resource management issues.

🔎 Suggested approach
     public void optionsUserRating(MovieRepoJpa movieRepoJpa,
                                   UserRatingRepoJpa userRatingRepoJpa,
-                                  User user){
+                                  User user,
+                                  Scanner sc){
         printOptionsUserRating();
-        Scanner sc = new Scanner(System.in);
         boolean running = true;

Update the call site at line 49 accordingly.


17-17: Unused import: DirectorRepo.

The DirectorRepo interface is imported but never used.


242-243: Creating duplicate repository instances instead of using injected ones.

Lines 242, 266, and 291 create new repository instances (ActorRepoJpa, DirectorRepoJpa, GenreRepoJpa) even though equivalent repos are passed as parameters to optionsMovies. Use the injected instances for consistency.

🔎 Example fix for case 6
                         //hämtar actor-objektet
-                        ActorRepoJpa actorRepo = new ActorRepoJpa(em);
-                        Optional<Actor> actorOpt = actorRepo.findByName(actorName);
+                        Optional<Actor> actorOpt = actorRepoJpa.findByName(actorName);

Also applies to: 266-267, 291-292

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc2e29e and 36188b3.

📒 Files selected for processing (5)
  • src/main/java/org/example/App.java (1 hunks)
  • src/main/java/org/example/CliAdminApp.java (1 hunks)
  • src/main/java/org/example/CliApp.java (1 hunks)
  • src/main/java/org/example/jpaimpl/MovieRepoJpa.java (4 hunks)
  • src/test/java/org/example/AppTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/org/example/AppTest.java
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/org/example/CliAdminApp.java (1)
src/main/java/org/example/seed/SeedUsers.java (1)
  • SeedUsers (9-153)
src/main/java/org/example/App.java (3)
src/main/java/org/example/DatabaseFiller.java (1)
  • DatabaseFiller (15-55)
src/main/java/org/example/JpaRunner.java (1)
  • JpaRunner (8-24)
src/main/java/org/example/JpaUtil.java (1)
  • JpaUtil (9-34)
🔇 Additional comments (5)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (2)

112-130: LGTM! Proper JPA implementations for getByDirector and getByActor.

The stub implementations have been replaced with proper JPQL queries. The getByDirector query correctly matches on the director entity, and getByActor properly uses a join on the actors collection.


100-109: Good refactoring of findByTitle to use Optional with stream.

The implementation correctly handles null/blank input and uses getResultStream().findFirst() which is cleaner than catching NoResultException.

src/main/java/org/example/App.java (2)

19-26: Good use of transactional seeding with database emptiness check.

The seeding logic correctly uses JpaRunner.runInTransaction for atomic seeding and guards with isDatabaseEmpty to avoid duplicate seeding.


29-77: LGTM! Clean resource management with try-with-resources.

The EntityManager lifecycle is properly managed, and the login flow with retry logic is well-structured.

src/main/java/org/example/CliAdminApp.java (1)

222-234: Logic error: inconsistent Optional usage.

Line 230 checks users.isEmpty() treating users as a collection, but line 233 calls users.ifPresent() treating it as an Optional. Based on the findByUserName method likely returning Optional<User>, the correct check should be users.isEmpty()users.isPresent() inverted, or simply use the Optional pattern consistently.

🔎 Proposed fix
                     var users = userRepo.findByUserName(userName);
                     em.getTransaction().commit();

-                    if (users.isEmpty()) {
+                    if (users.isEmpty()) {
                         System.out.println("No users found with username '" + userName + "'");
                     } else {
-                        users.ifPresent(u -> System.out.println("Found user: " + u.getUserName()));
+                        System.out.println("Found user: " + users.get().getUserName());
                     }

Likely an incorrect or invalid review comment.

Comment on lines +178 to +182
case 2 -> {
System.out.println("***** You have selected to list movies by language *****");
System.out.println("Enter Language: ");
String langInput = sc.nextLine().trim().toUpperCase();
Language lang = Language.valueOf(langInput);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling for enum parsing.

Language.valueOf(langInput) will throw IllegalArgumentException for invalid input, crashing the application.

🔎 Proposed fix
                     System.out.println("Enter Language: ");
                     String langInput = sc.nextLine().trim().toUpperCase();
-                    Language lang = Language.valueOf(langInput);
-                    movieRepoJpa.getMovieByLanguage(lang)
-                        .forEach(m-> System.out.println("- " + m.getTitle()));
+                    try {
+                        Language lang = Language.valueOf(langInput);
+                        movieRepoJpa.getMovieByLanguage(lang)
+                            .forEach(m-> System.out.println("- " + m.getTitle()));
+                    } catch (IllegalArgumentException e) {
+                        System.out.println("Invalid language: " + langInput);
+                    }
📝 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
case 2 -> {
System.out.println("***** You have selected to list movies by language *****");
System.out.println("Enter Language: ");
String langInput = sc.nextLine().trim().toUpperCase();
Language lang = Language.valueOf(langInput);
case 2 -> {
System.out.println("***** You have selected to list movies by language *****");
System.out.println("Enter Language: ");
String langInput = sc.nextLine().trim().toUpperCase();
try {
Language lang = Language.valueOf(langInput);
movieRepoJpa.getMovieByLanguage(lang)
.forEach(m-> System.out.println("- " + m.getTitle()));
} catch (IllegalArgumentException e) {
System.out.println("Invalid language: " + langInput);
}
🤖 Prompt for AI Agents
In src/main/java/org/example/CliApp.java around lines 178 to 182, the call
Language.valueOf(langInput) can throw IllegalArgumentException for invalid
input; wrap the parsing in a try-catch (or validate against Language.values()
first) to handle invalid inputs gracefully: catch IllegalArgumentException to
print a user-friendly error message and re-prompt or return to the menu, or use
a utility method that maps input to an Optional<Language> and handles absent
values without throwing.

System.out.println("Enter Genre: ");
String genreName = sc.nextLine();

GenreRepoJpa directorRepo = new GenreRepoJpa(em);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Misleading variable name: directorRepo is actually a GenreRepoJpa.

The variable is named directorRepo but holds a GenreRepoJpa instance.

🔎 Proposed fix
-                        GenreRepoJpa directorRepo = new GenreRepoJpa(em);
-                        Optional<Genre> genreOpt = directorRepo.findByName(genreName);
+                        GenreRepoJpa genreRepo = new GenreRepoJpa(em);
+                        Optional<Genre> genreOpt = genreRepo.findByName(genreName);
📝 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
GenreRepoJpa directorRepo = new GenreRepoJpa(em);
GenreRepoJpa genreRepo = new GenreRepoJpa(em);
Optional<Genre> genreOpt = genreRepo.findByName(genreName);
🤖 Prompt for AI Agents
In src/main/java/org/example/CliApp.java around line 291, the local variable is
named directorRepo while it is instantiated as a GenreRepoJpa, which is
misleading; rename the variable to genreRepo (or another name reflecting
GenreRepoJpa) and update all subsequent usages at/after this line to use the new
name so the variable type and identifier match.

Linus Westling and others added 2 commits December 19, 2025 16:27
Simplified the EntityManager mess for CliAdminApp.

TODO: Simplify em for CliApp.
Co-authored-by: Oscar Nidemar <oscar.nidemar@gmail.com>
Co-authored-by: Oskar Lundqvist <oskar.lundqvist3@icloud.com>
Co-authored-by: Mark Cavric <cavric_123@hotmail.se>
Co-authored-by: Linus Westling <westling.linus@gmail.com>
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

♻️ Duplicate comments (3)
src/main/java/org/example/jpaimpl/MovieRepoJpa.java (1)

192-203: Add entity alias to the language field in the query.

Line 199 uses language = :language but should use m.language = :language for consistency with other queries and to avoid potential ambiguity.

🔎 Proposed fix
         return em.createQuery(
-            "select m from Movie m where language = :language", Movie.class)
+            "select m from Movie m where m.language = :language", Movie.class)
             .setParameter("language", language)
             .getResultList();
src/main/java/org/example/CliApp.java (2)

199-207: Add error handling for enum parsing.

Line 204 uses Language.valueOf(langInput) without error handling. Invalid input will throw IllegalArgumentException and crash the application.

🔎 Proposed fix
                 case 2 -> {
                     System.out.println("***** You have selected to list movies by language *****");
                     System.out.println("Enter Language: ");
                     String langInput = sc.nextLine().trim().toUpperCase();
-                    Language lang = Language.valueOf(langInput);
-                    movieRepoJpa.getMovieByLanguage(lang)
-                        .forEach(m -> System.out.println("- " + m.getTitle()));
+                    try {
+                        Language lang = Language.valueOf(langInput);
+                        movieRepoJpa.getMovieByLanguage(lang)
+                            .forEach(m -> System.out.println("- " + m.getTitle()));
+                    } catch (IllegalArgumentException e) {
+                        System.out.println("Invalid language: " + langInput);
+                    }
                 }

321-340: Critical: NoSuchElementException when genre not found.

Lines 328-330 check if genreOpt.isEmpty() and print a message, but execution continues to line 332 which unconditionally calls genreOpt.get(). When the genre is not found, this throws NoSuchElementException.

🔎 Proposed fix
                 case 8 -> {
                     System.out.println("***** You have selected find a movie by genre *****");
                     System.out.println("Enter Genre: ");
                     String genreName = sc.nextLine();

                     Optional<Genre> genreOpt = genreRepoJpa.findByName(genreName);

                     if (genreOpt.isEmpty()) {
                         System.out.println("No genre found with name: " + genreName);
+                        break;
                     }

                     Genre genre = genreOpt.get();
                     List<Movie> moviesByGenre = movieRepoJpa.getMovieByGenre(genre.getName());

                     if (moviesByGenre.isEmpty()) {
                         System.out.println("No movies found in genre: " + genre.getName());
                     } else {
                         moviesByGenre.forEach(m -> System.out.println("- " + m.getTitle()));
                     }
                 }
🧹 Nitpick comments (1)
src/main/java/org/example/CliApp.java (1)

439-439: Use double literal for consistency.

Line 439 initializes a double variable with a float literal (-1.0f). While Java auto-converts this, using a double literal (-1.0 or -1.0d) would be more consistent with the variable type and rating operations throughout the codebase.

🔎 Proposed fix
-                    double rating = -1.0f;
+                    double rating = -1.0;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36188b3 and 44d5b68.

📒 Files selected for processing (8)
  • src/main/java/org/example/App.java (1 hunks)
  • src/main/java/org/example/CliAdminApp.java (1 hunks)
  • src/main/java/org/example/CliApp.java (1 hunks)
  • src/main/java/org/example/JpaUtil.java (1 hunks)
  • src/main/java/org/example/jpaimpl/MovieRepoJpa.java (4 hunks)
  • src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java (4 hunks)
  • src/main/java/org/example/pojo/UserRating.java (2 hunks)
  • src/main/java/org/example/repo/UserRatingRepo.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/example/repo/UserRatingRepo.java
  • src/main/java/org/example/JpaUtil.java
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/org/example/CliAdminApp.java (1)
src/main/java/org/example/JpaRunner.java (1)
  • JpaRunner (8-24)
src/main/java/org/example/App.java (3)
src/main/java/org/example/DatabaseFiller.java (1)
  • DatabaseFiller (15-55)
src/main/java/org/example/JpaRunner.java (1)
  • JpaRunner (8-24)
src/main/java/org/example/JpaUtil.java (1)
  • JpaUtil (9-34)
🔇 Additional comments (4)
src/main/java/org/example/pojo/UserRating.java (1)

27-27: LGTM!

The parameter type change from float to double improves precision for rating values and is consistent with the repository layer changes in UserRatingRepoJpa.

Also applies to: 55-55

src/main/java/org/example/jpaimpl/UserRatingRepoJpa.java (1)

21-21: LGTM!

The changes improve the API by:

  • Using double instead of float for better precision in rating values.
  • Returning boolean from rateMovie to indicate success/failure instead of void.
  • Handling null inputs gracefully by returning false instead of throwing exceptions.

These changes are consistent across the codebase and align with the corresponding entity changes in UserRating.java.

Also applies to: 60-70, 85-121

src/main/java/org/example/App.java (1)

14-80: LGTM!

The refactored main method improves the architecture by:

  • Runtime seeding with database emptiness check to avoid duplicate seeding.
  • Using JpaRunner for clean transactional boundaries.
  • Proper EntityManager lifecycle management with try-with-resources.
  • Clear separation between admin and user CLI flows.
  • Login retry loop with user-friendly exit option.
src/main/java/org/example/CliAdminApp.java (1)

15-348: LGTM!

The admin menu implementation demonstrates excellent practices:

  • Comprehensive input validation with clear error messages for numeric, date, and enum parsing.
  • Graceful handling of missing entities using Optional pattern without crashing.
  • Consistent transactional boundaries via JpaRunner.runInTransaction.
  • User-friendly feedback for all operations.
  • Proper handling of empty/invalid inputs throughout.

All previously identified issues have been addressed.

Comment on lines +135 to +166
public List<Movie> getMovieByReleaseDate(String from, String to) {
if (from == null || to == null || from.isEmpty() || to.isEmpty()) return List.of();

LocalDate fromDate;
LocalDate toDate;

try {
fromDate = LocalDate.parse(from, PLAIN_DATE);
toDate = LocalDate.parse(from, PLAIN_DATE);
} catch (DateTimeParseException e){
System.out.print("Invalid date format. Expected pattern: " + PLAIN_DATE);
return List.of();
}

if (fromDate.isAfter(toDate)) {
System.out.println("From-date cannot be after to-date");
return List.of();
}

try {
return em.createQuery(
"select m from Movie m where m.releaseDate between :from and :to order by m.releaseDate asc",
Movie.class)
.setParameter("from", fromDate)
.setParameter("to", toDate)
.getResultList();
} catch (Exception e) {
System.out.println("Error executing query: " + e.getMessage());
return List.of();
}

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical bug: parsing from parameter twice instead of to.

Line 143 parses the from parameter again instead of parsing the to parameter, causing both fromDate and toDate to have the same value. This breaks all date range queries.

🔎 Proposed fix
         try {
             fromDate = LocalDate.parse(from, PLAIN_DATE);
-            toDate = LocalDate.parse(from, PLAIN_DATE);
+            toDate = LocalDate.parse(to, PLAIN_DATE);
         } catch (DateTimeParseException e){
📝 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 List<Movie> getMovieByReleaseDate(String from, String to) {
if (from == null || to == null || from.isEmpty() || to.isEmpty()) return List.of();
LocalDate fromDate;
LocalDate toDate;
try {
fromDate = LocalDate.parse(from, PLAIN_DATE);
toDate = LocalDate.parse(from, PLAIN_DATE);
} catch (DateTimeParseException e){
System.out.print("Invalid date format. Expected pattern: " + PLAIN_DATE);
return List.of();
}
if (fromDate.isAfter(toDate)) {
System.out.println("From-date cannot be after to-date");
return List.of();
}
try {
return em.createQuery(
"select m from Movie m where m.releaseDate between :from and :to order by m.releaseDate asc",
Movie.class)
.setParameter("from", fromDate)
.setParameter("to", toDate)
.getResultList();
} catch (Exception e) {
System.out.println("Error executing query: " + e.getMessage());
return List.of();
}
}
public List<Movie> getMovieByReleaseDate(String from, String to) {
if (from == null || to == null || from.isEmpty() || to.isEmpty()) return List.of();
LocalDate fromDate;
LocalDate toDate;
try {
fromDate = LocalDate.parse(from, PLAIN_DATE);
toDate = LocalDate.parse(to, PLAIN_DATE);
} catch (DateTimeParseException e){
System.out.print("Invalid date format. Expected pattern: " + PLAIN_DATE);
return List.of();
}
if (fromDate.isAfter(toDate)) {
System.out.println("From-date cannot be after to-date");
return List.of();
}
try {
return em.createQuery(
"select m from Movie m where m.releaseDate between :from and :to order by m.releaseDate asc",
Movie.class)
.setParameter("from", fromDate)
.setParameter("to", toDate)
.getResultList();
} catch (Exception e) {
System.out.println("Error executing query: " + e.getMessage());
return List.of();
}
}
🤖 Prompt for AI Agents
In src/main/java/org/example/jpaimpl/MovieRepoJpa.java around lines 135 to 166,
the code mistakenly parses the "from" string twice so toDate is set from the
"from" parameter; change the second parse to use the "to" parameter (i.e.,
LocalDate.parse(to, PLAIN_DATE)) so fromDate and toDate reflect the intended
range, keep the existing DateTimeParseException handling and query logic
unchanged, and run unit/integration tests for date-range queries to verify the
fix.

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.

1 participant