Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/339Lr3BJ)
### How the tests work (and Docker requirement)

This project ships with an end‑to‑end CLI integration test suite that uses Testcontainers to spin up a temporary MySQL database.
Expand Down
Empty file modified mvnw
100644 → 100755
Empty file.
23 changes: 23 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,37 @@
<version>1.21.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.13</version>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.21.3</version>
</dependency>
</dependencies>
<build>

<plugins>


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
Expand Down
231 changes: 224 additions & 7 deletions src/main/java/com/example/Main.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.example;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.*;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
public class
Main {

static void main(String[] args) {
private Connection connection; // Koppla upp mot databas


public static void main(String[] args) {
if (isDevMode(args)) {
DevDatabaseInitializer.start();
}
new Main().run();
}

public void run() {

// Resolve DB settings with precedence: System properties -> Environment variables
String jdbcUrl = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL");
String dbUser = resolveConfig("APP_DB_USER", "APP_DB_USER");
Expand All @@ -26,13 +30,226 @@ public void run() {
"as system properties (-Dkey=value) or environment variables.");
}

try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) {
// Connection, sparas i instansvariabel
try {
this.connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass);
System.out.println("Connected to database successfully.");
} catch (SQLException e) {
throw new RuntimeException(e);
throw new RuntimeException("Could not connect to database", e);
}

//Todo: Starting point for your code

Scanner scanner = new Scanner(System.in);

// todo: Log in loop
while (true) {
System.out.print("Username (or 0 to exit): ");
String username = scanner.nextLine();
if (username.equals("0")) return;

System.out.print("Password (or 0 to exit): ");
String password = scanner.nextLine();
if (password.equals("0")) return;

if (login(username, password)) {
break;
} else {
System.out.println("Invalid username or password");
}
}

// todo: menu after successfully logged in
boolean running = true;

while (running) {
printMenu();
String choice = scanner.nextLine();

switch (choice) {
case "1" -> listMoonMissions();
case "2" -> getMoonMissionById(scanner);
case "3" -> countMissionsByYear(scanner);
case "4" -> createAccount(scanner);
case "5" -> updatePassword(scanner);
case "6" -> deleteAccount(scanner);
case "0" -> running = false;
default -> System.out.println("invalid");
}
}
}


// todo: LOGIN uses column `name` created from CONCAT in init.sql
private boolean login(String username, String password) {
String sql = "SELECT * FROM account WHERE name = ? AND password = ?";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, username);
stmt.setString(2, password);

ResultSet rs = stmt.executeQuery();
return rs.next();

} catch (SQLException e) {
throw new RuntimeException("Login failed", e);
}
}


// todo: print CLI menu
private void printMenu() {
System.out.println(" ---> MENU <--- ");
System.out.println("1) List moon missions");
System.out.println("2) Get moon mission");
System.out.println("3) Count missions by year");
System.out.println("4) Create account");
System.out.println("5) Update account password");
System.out.println("6) Delete account");
System.out.println("0) Exit");
}

// todo: choice 1 - List moon missions
private void listMoonMissions() {
String sql = "SELECT spacecraft FROM moon_mission";

try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {

while (rs.next()) {
System.out.println(rs.getString("spacecraft"));
}

} catch (SQLException e) {
throw new RuntimeException("Could not list missions", e);
}
}

// todo: choice 2 - Get mission by ID
private void getMoonMissionById(Scanner scanner) {
System.out.print("mission_id: ");
int id = Integer.parseInt(scanner.nextLine());

String sql = "SELECT * FROM moon_mission WHERE mission_id = ?";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, id);
ResultSet rs = stmt.executeQuery();

if (rs.next()) {
System.out.println(
rs.getInt("mission_id") + " " +
rs.getString("spacecraft") + " " +
rs.getString("launch_date")
);
System.out.println("------------");
} else {
System.out.println("Invalid username or password");
}

} catch (SQLException e) {
throw new RuntimeException(e);
}
}
Comment on lines +128 to +153
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

Wrong error message when mission ID is not found

In getMoonMissionById, the else branch currently prints:

System.out.println("Invalid username or password");

This is misleading in the context of looking up a mission and will confuse users (and likely tests that expect a mission‑specific message).

Apply a small fix like:

-            } else {
-                System.out.println("Invalid username or password");
-            }
+            } else {
+                System.out.println("No mission found for that id");
+            }

Optionally, you may also want to validate that the entered ID is numeric and handle NumberFormatException with a simple invalid message, but that’s not strictly required by the assignment.

🤖 Prompt for AI Agents
In src/main/java/com/example/Main.java around lines 128 to 153, the else branch
prints an unrelated "Invalid username or password" message when no mission is
found; change that message to something mission‑appropriate (e.g., "Mission not
found" or "No mission with that ID") so users/tests get the correct feedback,
and optionally add a NumberFormatException catch around parsing the input to
print a simple "Invalid mission ID" message if non‑numeric input is entered.



// todo: choice 3 - Count missions by year
private void countMissionsByYear(Scanner scanner) {
System.out.print("Total missions for 2019: ");
int year = Integer.parseInt(scanner.nextLine());

String sql = "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date) = ?";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, year);
ResultSet rs = stmt.executeQuery();
rs.next();
System.out.println(rs.getInt(1));

} catch (SQLException e) {
throw new RuntimeException(e);
}
}
Comment on lines +156 to +172
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

Prompt for year should not hardcode 2019

countMissionsByYear currently prompts:

System.out.print("Total missions for 2019: ");

but then reads an arbitrary year and queries using that year. This conflicts with the “given year” requirement and can be confusing.

A clearer and spec‑aligned version would be:

-        System.out.print("Total missions for 2019: ");
+        System.out.print("year: ");
         int year = Integer.parseInt(scanner.nextLine());

The rest of the query logic (using YEAR(launch_date) and printing the count) looks good.

🤖 Prompt for AI Agents
In src/main/java/com/example/Main.java around lines 156 to 172, the prompt
string currently hardcodes "Total missions for 2019: " which is inconsistent
with reading an arbitrary year; change the prompt to a generic, accurate message
(for example "Enter year: " or "Total missions for year: ") so the prompt is
shown before reading input and matches the year being parsed and used in the
query.


//todo: Choice 4 - Add costumer method.
private void createAccount(Scanner scanner) {
System.out.print("first name: ");
String first = scanner.nextLine();

System.out.print("last name: ");
String last = scanner.nextLine();

System.out.print("ssn: ");
String ssn = scanner.nextLine();

System.out.print("password: ");
String pw = scanner.nextLine();

String sql = """
INSERT INTO account (first_name, last_name, ssn, password)
VALUES (?, ?, ?, ?)
""";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, first);
stmt.setString(2, last);
stmt.setString(3, ssn);
stmt.setString(4, pw);
stmt.executeUpdate();

System.out.println("created");

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


// todo: Choice - 5 Update password method
private void updatePassword(Scanner scanner) {
System.out.print("user_id: ");
int id = Integer.parseInt(scanner.nextLine());

System.out.print("new password: ");
String newPw = scanner.nextLine();

String sql = "UPDATE account SET password = ? WHERE user_id = ?";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, newPw);
stmt.setInt(2, id);
stmt.executeUpdate();

System.out.println("updated");

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

// todo: Choice 6 - Delete account method
private void deleteAccount(Scanner scanner) {
System.out.print("user_id: ");
int id = Integer.parseInt(scanner.nextLine());

String sql = "DELETE FROM account WHERE user_id = ?";

try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setInt(1, id);
stmt.executeUpdate();

System.out.println("deleted");

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






/**
* Determines if the application is running in development mode based on system properties,
* environment variables, or command-line arguments.
Expand Down
Loading