Skip to content

Lab3#20

Open
AnnaZiafar wants to merge 8 commits intomainfrom
Lab3
Open

Lab3#20
AnnaZiafar wants to merge 8 commits intomainfrom
Lab3

Conversation

@AnnaZiafar
Copy link

@AnnaZiafar AnnaZiafar commented Dec 14, 2025

Summary by CodeRabbit

  • New Features

    • Interactive sign-in and menu-driven app UI
    • Account management: create, update password, delete, authenticate
    • Moon mission queries: list missions, fetch by ID, count/filter by year
    • Improved DB connectivity with connection pooling
  • Documentation

    • Added review-deadline badge and noted Docker/Testcontainers requirement for running tests
  • Chores

    • Added database and logging libraries to project dependencies

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 14, 2025

Walkthrough

Adds connection pooling, repository interfaces and implementations, refactors Main to a menu-driven, authenticated UI using the repositories, and updates README and pom with a test/docker note and three new dependencies.

Changes

Cohort / File(s) Summary
Documentation & Build
README.md, pom.xml
README: added review-deadline badge and Docker/Testcontainers note under "How the tests work". pom.xml: added dependencies org.apache.commons:commons-dbcp2:2.13.0, org.slf4j:slf4j-nop:2.0.17, org.hibernate.orm:hibernate-core:7.1.11.Final.
Connection Pooling Utility
src/main/java/com/example/DataSource.java
New static utility class that configures an Apache DBCP2 BasicDataSource using system property → env var precedence; exposes getConnection() and getters for JDBC URL, user, and password.
Repository Interfaces
src/main/java/repositories/AccountInter.java, src/main/java/repositories/MoonMissionInter.java
New interfaces defining account operations (validateLogIn, createAccount, deleteAccount, updatePassword) and mission queries (displayColumn, getMissionFromID, allMissionsConductedInYear).
Repository Implementations
src/main/java/repositories/AccountRepo.java, src/main/java/repositories/MoonMissionRepo.java
New classes implementing the above interfaces; perform JDBC operations via DataSource.getConnection() using PreparedStatement, execute queries/inserts/updates, print outcomes, and wrap SQLExceptions in RuntimeExceptions.
Application Refactor
src/main/java/com/example/Main.java
Reworked Main to use AccountRepo and MoonMissionRepo, added sign-in flow (validateSignIn), interactive console menu, account management (create/update/delete), mission queries (list, fetch by ID, count by year), and input validation; main now throws SQLException.

Sequence Diagram

sequenceDiagram
    participant User
    participant Main
    participant AccountRepo
    participant MoonMissionRepo
    participant DataSource
    participant Database

    User->>Main: Start app
    Main->>User: Prompt credentials
    User->>Main: Submit username/password
    Main->>AccountRepo: validateLogIn(username, password)
    AccountRepo->>DataSource: getConnection()
    DataSource->>Database: provide pooled connection
    AccountRepo->>Database: SELECT ... FROM account WHERE ...
    Database-->>AccountRepo: result (row/no row)
    AccountRepo-->>Main: boolean (authenticated?)
    alt authenticated
        Main->>User: Show menu
        User->>Main: Choose operation
        opt List missions
            Main->>MoonMissionRepo: displayColumn("*") / displayAll
            MoonMissionRepo->>DataSource: getConnection()
            DataSource->>Database: provide connection
            MoonMissionRepo->>Database: SELECT * FROM moon_mission
            Database-->>MoonMissionRepo: result set
            MoonMissionRepo-->>Main: formatted mission list
            Main-->>User: display missions
        end
        opt Create account
            Main->>User: collect name, ssn, password
            Main->>AccountRepo: createAccount(...)
            AccountRepo->>DataSource: getConnection()
            AccountRepo->>Database: INSERT INTO account (...)
            Database-->>AccountRepo: update count
            AccountRepo-->>Main: success/failure
            Main-->>User: show result
        end
    else not authenticated
        Main->>User: Show error, retry
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review SQL parameter usage and ensure no string-concatenated SQL remains (especially year matching and displayColumn).
  • Verify try-with-resources / connection/statement/resultset closing in AccountRepo and MoonMissionRepo.
  • Confirm authentication logic and password validation in Main are robust and consistent.
  • Check DataSource configuration precedence and default values for correctness and security (credentials handling).
  • Consider whether wrapping SQLExceptions in RuntimeException aligns with overall error-handling strategy.

Poem

🐰
I hopped into code, tail all aflutter,
Pooled connections hum like soft butter,
Repos tidy rows with a neat little song,
Menus and sign-ins keep everything strong,
A carrot for tests — Docker hums along!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.03% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Lab3' is vague and generic, providing no meaningful information about the changeset's primary purpose or the substantial modifications made. Replace with a descriptive title that summarizes the main change, such as 'Add account authentication and repository-based data access layer' or 'Implement user sign-in flow and database abstraction with repositories'.
✅ 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

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

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

🧹 Nitpick comments (2)
src/main/java/repositories/MoonMissionInter.java (1)

1-23: Interface contract vs implementation: document * semantics precisely (and match behavior)
JavaDoc says * means “all columns”; make sure the repo implementation actually supports that (currently it doesn’t).

src/main/java/repositories/AccountInter.java (1)

1-42: Consider returning results/status instead of printing inside repo methods
Even for a CLI app, returning boolean/Optional/row counts (and letting Main print) usually makes the code easier to test and evolve.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e629e94 and c36f948.

📒 Files selected for processing (8)
  • README.md (1 hunks)
  • pom.xml (1 hunks)
  • src/main/java/com/example/DataSource.java (1 hunks)
  • src/main/java/com/example/Main.java (2 hunks)
  • src/main/java/repositories/AccountInter.java (1 hunks)
  • src/main/java/repositories/AccountRepo.java (1 hunks)
  • src/main/java/repositories/MoonMissionInter.java (1 hunks)
  • src/main/java/repositories/MoonMissionRepo.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/repositories/MoonMissionRepo.java (1)
src/main/java/com/example/DataSource.java (1)
  • DataSource (7-50)
src/main/java/com/example/Main.java (3)
src/main/java/repositories/AccountRepo.java (1)
  • AccountRepo (10-96)
src/main/java/com/example/DevDatabaseInitializer.java (1)
  • DevDatabaseInitializer (6-24)
src/main/java/com/example/DataSource.java (1)
  • DataSource (7-50)
src/main/java/repositories/AccountRepo.java (1)
src/main/java/com/example/DataSource.java (1)
  • DataSource (7-50)
🔇 Additional comments (3)
README.md (1)

1-83: Docs update is clear; Docker prerequisite is correctly called out
Nice addition, especially the IntelliJ + precedence notes.

pom.xml (1)

54-68: and

src/main/java/com/example/DataSource.java (1)

7-20: The file src/main/java/com/example/DataSource.java could not be located in the repository, so the specific code issues mentioned in this review cannot be verified. Without access to the actual code, I cannot confirm:

  • Whether resolveConfig() returns null values
  • Whether Hibernate is used in this project
  • The actual content at lines 22-49
  • Whether the suggested fixes are applicable to the actual codebase

Please verify that the file path is correct and the file exists in the repository before applying the suggested changes.

Comment on lines +14 to 20
static void main(String[] args) throws SQLException {
if (isDevMode(args)) {
DevDatabaseInitializer.start();
}
new Main().run();

}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: main must be public static void main(String[] args)
Package-private main won’t be a valid entrypoint when running the jar/class normally.

-    static void main(String[] args) throws SQLException {
+    public static void main(String[] args) throws SQLException {
         if (isDevMode(args)) {
             DevDatabaseInitializer.start();
         }
         new Main().run();
 
     }
📝 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
static void main(String[] args) throws SQLException {
if (isDevMode(args)) {
DevDatabaseInitializer.start();
}
new Main().run();
}
public static void main(String[] args) throws SQLException {
if (isDevMode(args)) {
DevDatabaseInitializer.start();
}
new Main().run();
}
🤖 Prompt for AI Agents
In src/main/java/com/example/Main.java around lines 14 to 20, the main method is
declared package-private as "static void main(String[] args) throws
SQLException" which prevents the JVM from finding it as an entry point; change
the signature to the standard public static void main(String[] args) (you can
keep or handle the throws SQLException inside the method or catch it), ensure
visibility is public and retain existing logic (call
DevDatabaseInitializer.start() when isDevMode(args) and then new Main().run())
so the class is runnable as a jar.

Comment on lines +84 to +89
private void deleteAccount(AccountRepo accountRepo) {
System.out.print("Enter userId for the account that you would like to delete: ");
int userId = Integer.parseInt(scanner.nextLine().trim());

accountRepo.deleteAccount(userId);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unvalidated Integer.parseInt(...) can crash the CLI
deleteAccount, updatePassword, and getMissionFromID will throw NumberFormatException on bad input and terminate the app; consider a small “readInt” helper with retry/abort behavior.

Also applies to: 99-110, 123-129

🤖 Prompt for AI Agents
In src/main/java/com/example/Main.java around lines 84-89 (and similarly for
99-110 and 123-129), user input is parsed directly with Integer.parseInt which
throws NumberFormatException on bad input and will crash the CLI; implement a
small reusable readInt helper that loops prompting the user, trims input,
catches NumberFormatException, shows a friendly error and reprompts, and accepts
a special abort token (e.g., "q" or "cancel") to return an OptionalInt or throw
a controlled exception so callers can abort gracefully; replace direct
Integer.parseInt calls in deleteAccount, updatePassword, and getMissionFromID
with this helper and handle the abort/empty result to avoid terminating the app.

Comment on lines +91 to +97
private boolean validPassword(String password){
if(password.isBlank() || password.length() < 6){
System.out.println("Error. Password must be at least 8 characters long.");
return false;
}
return true;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Password validation: condition and message disagree
You check < 6 but print “at least 8 characters”. Pick one (tests often care about exact behavior).

     private boolean validPassword(String password){
-        if(password.isBlank() || password.length() < 6){
+        if(password.isBlank() || password.length() < 8){
             System.out.println("Error. Password must be at least 8 characters long.");
             return false;
         }
         return true;
     }
📝 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
private boolean validPassword(String password){
if(password.isBlank() || password.length() < 6){
System.out.println("Error. Password must be at least 8 characters long.");
return false;
}
return true;
}
private boolean validPassword(String password){
if(password.isBlank() || password.length() < 8){
System.out.println("Error. Password must be at least 8 characters long.");
return false;
}
return true;
}
🤖 Prompt for AI Agents
In src/main/java/com/example/Main.java around lines 91-97 the password check and
error message disagree: the code checks for password.length() < 6 but prints "at
least 8 characters long"; update the validation to enforce the intended minimum
length (choose 8) by changing the length check to password.length() < 8 and keep
the error message as "Error. Password must be at least 8 characters long." so
behavior and message match.

Comment on lines +9 to +26
public class MoonMissionRepo implements MoonMissionInter{
@Override
public void displayColumn(String columnName) {
String query = "select * from moon_mission";

try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(query)) {

ResultSet result = pS.executeQuery();
while (result.next()) {
String name = result.getString(columnName);
System.out.println(name);
}

} catch (SQLException e) {
throw new RuntimeException(e);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

displayColumn("*") isn’t implemented; invalid column names will crash the command
If you want to support “all columns”, you need to iterate ResultSetMetaData rather than call getString("*"). Also consider validating columnName against a small allowlist (e.g., spacecraft) if it’s user-provided.

     public void displayColumn(String columnName) {
         String query = "select * from moon_mission";

         try (Connection con = DataSource.getConnection();
              PreparedStatement pS = con.prepareStatement(query)) {

-            ResultSet result = pS.executeQuery();
-            while (result.next()) {
-                String name = result.getString(columnName);
-                System.out.println(name);
-            }
+            try (ResultSet result = pS.executeQuery()) {
+                while (result.next()) {
+                    if ("*".equals(columnName)) {
+                        ResultSetMetaData meta = result.getMetaData();
+                        int columns = meta.getColumnCount();
+                        for (int i = 1; i <= columns; i++) {
+                            System.out.print(meta.getColumnName(i) + "=" + result.getString(i));
+                            System.out.print(i == columns ? "\n" : ", ");
+                        }
+                    } else {
+                        System.out.println(result.getString(columnName));
+                    }
+                }
+            }

         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
     }
🤖 Prompt for AI Agents
In src/main/java/repositories/MoonMissionRepo.java around lines 9 to 26, the
method currently calls result.getString(columnName) which will fail for
columnName == "*" and for invalid user-supplied names; change the logic to first
validate columnName against a small allowlist (e.g., "spacecraft",
"mission_date", etc.) and if columnName equals "*" iterate ResultSetMetaData to
read and print every column by name for each row, otherwise call
getString(validatedColumnName); ensure invalid names are handled gracefully
(throw IllegalArgumentException or log and return) rather than letting a
SQLException occur.

Comment on lines +57 to +76
@Override
public void allMissionsConductedInYear(String year) {
String query = "select count(*) from moon_mission where launch_date like ?";

try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(query)) {

int numMissions = 0;
pS.setString(1, year.trim() + "%");
ResultSet result = pS.executeQuery();
if (result.next()){
numMissions = result.getInt(1);
}

System.out.println("There were " + numMissions + " moon missions registered during " + year + ".\n");

} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Year filtering via LIKE is brittle; keep the exception cause
launch_date like 'YYYY%' depends on how launch_date is stored/converted. If it’s a DATE/TIMESTAMP, prefer YEAR(launch_date) = ? (MySQL) or a range filter. Also throw new RuntimeException() drops the original cause.

     public void allMissionsConductedInYear(String year) {
-        String query = "select count(*) from moon_mission where launch_date like ?";
+        String query = "select count(*) from moon_mission where YEAR(launch_date) = ?";

         try (Connection con = DataSource.getConnection();
              PreparedStatement pS = con.prepareStatement(query)) {

             int numMissions = 0;
-            pS.setString(1, year.trim() + "%");
-            ResultSet result = pS.executeQuery();
-            if (result.next()){
-                numMissions = result.getInt(1);
-            }
+            pS.setInt(1, Integer.parseInt(year.trim()));
+            try (ResultSet result = pS.executeQuery()) {
+                if (result.next()) numMissions = result.getInt(1);
+            }

             System.out.println("There were " + numMissions + " moon missions registered during " + year + ".\n");

         } catch (SQLException e) {
             e.printStackTrace();
-            throw new RuntimeException();
+            throw new RuntimeException(e);
         }
     }
🤖 Prompt for AI Agents
In src/main/java/repositories/MoonMissionRepo.java around lines 57 to 76, the
query uses "launch_date LIKE 'YYYY%'" which is brittle for DATE/TIMESTAMP
columns and the catch block throws a RuntimeException without preserving the
original SQLException; change the SQL to use a year-based filter (e.g.,
YEAR(launch_date) = ? for MySQL or a BETWEEN range for DBs without YEAR()) and
bind an integer year parameter, or construct start/end dates and use
"launch_date BETWEEN ? AND ?"; in the catch block rethrow while preserving the
cause (for example throw new RuntimeException(e) or rethrow the SQLException
wrapped) so the original error details are not lost.

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

♻️ Duplicate comments (2)
src/main/java/com/example/Main.java (2)

14-14: Critical: main must be public to be a valid entry point.

The main method is declared package-private (static void main), which prevents the JVM from recognizing it as an application entry point when running the jar.

Apply this diff:

-    static void main(String[] args) throws SQLException {
+    public static void main(String[] args) throws SQLException {

86-86: Unvalidated Integer.parseInt will crash on invalid input.

At lines 86, 101, and 125, user input is parsed directly with Integer.parseInt, which throws NumberFormatException on bad input and terminates the app. This degrades the user experience in a menu-driven CLI.

Consider implementing a reusable readInt() helper that catches the exception, prompts the user again, and allows them to abort gracefully (e.g., by entering "q" or "cancel").

Also applies to: 101-101, 125-125

🧹 Nitpick comments (4)
src/main/java/repositories/AccountRepo.java (1)

37-48: Username collision handling missing.

The generated username (first 3 chars of first name + first 3 chars of last name) can collide when multiple users share the same name pattern. The insert will fail with a constraint violation if name has a unique constraint, but the current code prints a generic error message.

Consider adding a suffix (e.g., sequential number or random digits) to handle collisions, or catch the specific constraint violation and provide a clearer message.

         } catch (SQLException e) {
+            if (e.getMessage() != null && e.getMessage().contains("Duplicate entry")) {
+                System.out.println("Error. Username already exists. Please try a different name combination.");
+                return;
+            }
             throw new RuntimeException(e);
         }
src/main/java/com/example/Main.java (3)

12-12: Scanner resource leak: field-level Scanner never closed.

The Scanner instance created at line 12 wraps System.in and is never closed. While this won't cause issues in a short-running CLI app, it's a resource leak and can trigger static analysis warnings.

Consider adding a shutdown hook or closing the scanner in a finally block when the program exits. For a simple CLI, you might suppress the warning with a comment explaining System.in is managed by the JVM.

private final Scanner scanner = new Scanner(System.in); // Not closed: System.in lifecycle managed by JVM

166-166: Redundant null check on Scanner input.

At line 166, choice != null is unnecessary because scanner.nextLine() never returns null (it returns an empty string if the input is empty).

Simplify to:

-            if (choice != null && choice.trim().equals("0"))
+            if (choice.trim().equals("0"))

Or even simpler, since choice is already trimmed at line 164:

-            if (choice != null && choice.trim().equals("0"))
+            if (choice.equals("0"))

153-169: Sign-in allows unlimited retry attempts.

The validateSignIn method loops indefinitely until valid credentials are entered or the user explicitly exits. While functional for a lab, this could be improved with a maximum retry limit to prevent brute-force attempts.

For production systems, consider adding a retry limit (e.g., 3 attempts) and potentially a lockout mechanism or delay after failed attempts.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c36f948 and 9389593.

📒 Files selected for processing (2)
  • src/main/java/com/example/Main.java (2 hunks)
  • src/main/java/repositories/AccountRepo.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/java/repositories/AccountRepo.java (1)
src/main/java/com/example/DataSource.java (1)
  • DataSource (7-50)
src/main/java/com/example/Main.java (2)
src/main/java/com/example/DevDatabaseInitializer.java (1)
  • DevDatabaseInitializer (6-24)
src/main/java/com/example/DataSource.java (1)
  • DataSource (7-50)
🔇 Additional comments (2)
src/main/java/com/example/Main.java (2)

92-93: Password validation now uses 6 characters minimum.

The validation at line 92 checks password.length() < 6 and the message at line 93 says "at least 6 characters long", so they are now consistent. However, note that this differs from the earlier past review which suggested 8 characters as a best practice for security.

If this is production code (not just a lab), consider increasing the minimum to 8 characters for better security.


115-115: LGTM! Year regex now correctly validates 1900s and 2000s.

The regex ^(19|20)\\d{2}$ properly matches four-digit years in the ranges 1900–1999 and 2000–2099, fixing the previous issue.

Comment on lines +13 to +27
public boolean validateLogIn(String username, String password) {
String userQuery = "select * from account where name = ? and password = ?";

try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(userQuery)) {

pS.setString(1, username);
pS.setString(2, password);
ResultSet result = pS.executeQuery();
return result.next();

} catch (SQLException e) {
throw new RuntimeException(e);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

ResultSet resource leak in validateLogIn.

The ResultSet returned by pS.executeQuery() at line 21 is not explicitly closed. While the Connection and PreparedStatement are managed by try-with-resources, the ResultSet is not, creating a potential resource leak.

Apply this diff to ensure proper resource cleanup:

     public boolean validateLogIn(String username, String password) {
         String userQuery = "select * from account where name = ? and password = ?";
 
         try (Connection con = DataSource.getConnection();
-             PreparedStatement pS = con.prepareStatement(userQuery)) {
+             PreparedStatement pS = con.prepareStatement(userQuery);
+             ResultSet result = pS.executeQuery()) {
 
             pS.setString(1, username);
             pS.setString(2, password);
-            ResultSet result = pS.executeQuery();
             return result.next();
 
         } catch (SQLException e) {
             throw new RuntimeException(e);
         }
     }

Wait, that's incorrect because we set parameters after creating the ResultSet. Let me fix:

     public boolean validateLogIn(String username, String password) {
         String userQuery = "select * from account where name = ? and password = ?";
 
         try (Connection con = DataSource.getConnection();
              PreparedStatement pS = con.prepareStatement(userQuery)) {
 
             pS.setString(1, username);
             pS.setString(2, password);
-            ResultSet result = pS.executeQuery();
-            return result.next();
+            try (ResultSet result = pS.executeQuery()) {
+                return result.next();
+            }
 
         } catch (SQLException e) {
             throw new RuntimeException(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 boolean validateLogIn(String username, String password) {
String userQuery = "select * from account where name = ? and password = ?";
try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(userQuery)) {
pS.setString(1, username);
pS.setString(2, password);
ResultSet result = pS.executeQuery();
return result.next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public boolean validateLogIn(String username, String password) {
String userQuery = "select * from account where name = ? and password = ?";
try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(userQuery)) {
pS.setString(1, username);
pS.setString(2, password);
try (ResultSet result = pS.executeQuery()) {
return result.next();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
🤖 Prompt for AI Agents
In src/main/java/repositories/AccountRepo.java around lines 13 to 27, the
ResultSet from pS.executeQuery() is not closed and executeQuery must be called
only after parameters are set; fix by setting the PreparedStatement parameters
first, then call executeQuery and wrap the returned ResultSet in its own
try-with-resources (try (ResultSet rs = pS.executeQuery()) { return rs.next();
}) so the ResultSet is always closed while keeping the Connection and
PreparedStatement in their existing try-with-resources.

try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(addUser)) {

String username = firstName.substring(0, 3) + lastName.substring(0, 3);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential StringIndexOutOfBoundsException if validation is bypassed.

The username generation at line 37 assumes firstName and lastName each have at least 3 characters. While Main.createAccount validates this (lines 56-66), calling AccountRepo.createAccount directly from elsewhere could cause a runtime exception.

Apply this diff to add defensive validation:

     public void createAccount(String firstName, String lastName, String password, String ssn) {
         String addUser = "insert into account (name, password, first_name, last_name, ssn) " +
                 "values (?, ?, ?, ?, ?)";
 
         try (Connection con = DataSource.getConnection();
              PreparedStatement pS = con.prepareStatement(addUser)) {
 
+            if (firstName.length() < 3 || lastName.length() < 3) {
+                throw new IllegalArgumentException("First name and last name must each be at least 3 characters");
+            }
             String username = firstName.substring(0, 3) + lastName.substring(0, 3);
📝 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
String username = firstName.substring(0, 3) + lastName.substring(0, 3);
public void createAccount(String firstName, String lastName, String password, String ssn) {
String addUser = "insert into account (name, password, first_name, last_name, ssn) " +
"values (?, ?, ?, ?, ?)";
try (Connection con = DataSource.getConnection();
PreparedStatement pS = con.prepareStatement(addUser)) {
if (firstName.length() < 3 || lastName.length() < 3) {
throw new IllegalArgumentException("First name and last name must each be at least 3 characters");
}
String username = firstName.substring(0, 3) + lastName.substring(0, 3);
🤖 Prompt for AI Agents
In src/main/java/repositories/AccountRepo.java around line 37, the username is
built by taking substring(0,3) of firstName and lastName which can throw
StringIndexOutOfBoundsException if either is null or shorter than 3 chars; add
defensive validation at the start of createAccount to check that firstName and
lastName are non-null and length >= 3 and throw an IllegalArgumentException with
a clear message if they are not, and then keep the existing substring logic (or
alternatively build the username using substring(0, Math.min(3, s.length())) if
you prefer to accept shorter names) so the method cannot crash when called
directly.

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