diff --git a/README.md b/README.md index ec42fc0..b33aba5 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,56 @@ If you want to learn more about building native executables, please consult **Import/Export** > **Import Data** > **From File**. + - Select the `doc/insomnia/insomnia.json` file. + - This will import all relevant requests for Tasky. + +3. **Manual Setup (Optional)** + + - Alternatively, you can create a new request manually: + - Click on the **Create** button and select **Request**. + - Choose **GraphQL Query** as the request type. + - Set the request URL to `http://localhost:8080/graphql`. + - Run the app in dev mode using: + ```shell + ./mvnw quarkus:dev # if on linux + .\mvnw.cmd quarkus:dev # if on windows powershell + ``` + - Paste your GraphQL query (for example, to list all tasks): + + ```graphql + query { + listAll { + taskId + title + description + tags { + name + } + } + } + ``` + + - Click **Send** to execute the query and see the results. + +4. **Tip:** + You can save your requests in a collection for easy access later. \ No newline at end of file diff --git a/doc/insomnia/insomnia.json b/doc/insomnia/insomnia.json new file mode 100644 index 0000000..bf2bbc9 --- /dev/null +++ b/doc/insomnia/insomnia.json @@ -0,0 +1,221 @@ +{ + "_type": "export", + "__export_format": 4, + "__export_date": "2025-06-11T15:07:31.764Z", + "__export_source": "insomnia.desktop.app:v10.3.1", + "resources": [ + { + "_id": "req_890f0fcd88c547caa3f21524c28bd167", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1749654422099, + "created": 1748443055314, + "url": "http://localhost:8080/graphql", + "name": "newTask", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/graphql", + "text": "{\"query\":\"mutation {\\n newTask(\\n task: {\\n description: \\\"deleteme\\\"\\n priority: Info\\n tagList: [Personal, Work]\\n creation: \\\"2025-05-28T11:00:00Z\\\"\\n conclusion: null\\n }\\n )\\n}\"}" + }, + "parameters": [], + "headers": [ + { + "name": "User-Agent", + "value": "insomnia/10.3.1" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": {}, + "metaSortKey": -1748443055314, + "isPrivate": false, + "pathParameters": [], + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "wrk_3d521749d9754acc9979a11ac55e42a1", + "parentId": null, + "modified": 1748441235305, + "created": 1741269754962, + "name": "tasky", + "description": "", + "scope": "collection", + "_type": "workspace" + }, + { + "_id": "req_37e6e6f5c32e495a850a4872150d34d5", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1749653836448, + "created": 1748443359584, + "url": "http://localhost:8080/graphql", + "name": "getTaskId", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/graphql", + "text": "{\"query\":\"query {\\n\\tsearchById(id: 7) {\\n\\t\\tid\\n\\t\\tdescription\\n\\t\\tpriority\\n\\t\\ttagList\\n\\t\\tcreation\\n\\t\\tconclusion\\n\\t}\\n}\\n\"}" + }, + "parameters": [], + "headers": [ + { + "name": "User-Agent", + "value": "insomnia/10.3.1" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": {}, + "metaSortKey": -1748443055264, + "isPrivate": false, + "pathParameters": [], + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "req_17c2a41c6d064f9a98b0d8afdb653e9f", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1748454896283, + "created": 1748453240683, + "url": "http://localhost:8080/graphql", + "name": "deleteTaskId", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/graphql", + "text": "{\"query\":\"mutation {\\n deleteById(id: 5)\\n}\"}" + }, + "parameters": [], + "headers": [ + { + "name": "User-Agent", + "value": "insomnia/10.3.1" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": {}, + "metaSortKey": -1748443055214, + "isPrivate": false, + "pathParameters": [], + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "req_b394fd4e6b0b4f059d3a8d70c22506aa", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1748869202698, + "created": 1748868351221, + "url": "http://localhost:8080/graphql", + "name": "editTaskId", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/graphql", + "text": "{\"query\":\"mutation {\\n editById(\\n id: 1,\\n updatedTask: {\\n description: \\\"Updated description\\\"\\n priority: High\\n tagList: [Personal]\\n creation: \\\"2024-06-01T12:00:00Z\\\"\\n conclusion: \\\"2024-06-02T12:00:00Z\\\"\\n }\\n ) {\\n description\\n priority\\n tagList\\n creation\\n conclusion\\n }\\n}\"}" + }, + "parameters": [], + "headers": [ + { + "name": "User-Agent", + "value": "insomnia/10.3.1" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": {}, + "metaSortKey": -1748443055164, + "isPrivate": false, + "pathParameters": [], + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "req_b78a363cdf8c4f98833251aeb074b6c3", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1749051097383, + "created": 1749051081703, + "url": "http://localhost:8080/graphql", + "name": "listAll", + "description": "", + "method": "POST", + "body": { + "mimeType": "application/graphql", + "text": "{\"query\":\"query {\\n listAll {\\n description\\n priority\\n tagList\\n creation\\n conclusion\\n }\\n}\"}" + }, + "parameters": [], + "headers": [ + { + "name": "User-Agent", + "value": "insomnia/10.3.1" + }, + { + "name": "Content-Type", + "value": "application/json" + } + ], + "authentication": {}, + "metaSortKey": -1748443055114, + "isPrivate": false, + "pathParameters": [], + "settingStoreCookies": true, + "settingSendCookies": true, + "settingDisableRenderRequestBody": false, + "settingEncodeUrl": true, + "settingRebuildPath": true, + "settingFollowRedirects": "global", + "_type": "request" + }, + { + "_id": "env_d76da4c90990988c348bc28a0f33427c80a290a0", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1748441235304, + "created": 1741269754966, + "name": "Base Environment", + "data": {}, + "dataPropertyOrder": null, + "color": null, + "isPrivate": false, + "metaSortKey": 1741269754966, + "environmentType": "kv", + "_type": "environment" + }, + { + "_id": "jar_d76da4c90990988c348bc28a0f33427c80a290a0", + "parentId": "wrk_3d521749d9754acc9979a11ac55e42a1", + "modified": 1748441235351, + "created": 1748441235351, + "name": "Default Jar", + "cookies": [], + "_type": "cookie_jar" + } + ] +} \ No newline at end of file diff --git a/src/main/java/br/com/pedr0limpio/services/MySQLDAO.java b/src/main/java/br/com/pedr0limpio/services/MySQLDAO.java index 2280c66..78954e3 100644 --- a/src/main/java/br/com/pedr0limpio/services/MySQLDAO.java +++ b/src/main/java/br/com/pedr0limpio/services/MySQLDAO.java @@ -40,9 +40,25 @@ private void loadDatabaseConfig() { } } + private void checkDatabaseConfig() { + if (url == null || url.trim().isEmpty() || + username == null || username.trim().isEmpty() || + password == null || password.trim().isEmpty()) { + throw new RuntimeException("Database configuration is missing or empty. Please check application.properties."); + } + // Try a simple connection to validate credentials + try (Connection conn = DriverManager.getConnection(url, username, password)) { + // Connection successful, do nothing + } catch (SQLException e) { + throw new RuntimeException("Database credentials are invalid or database is unreachable: " + e.getMessage(), e); + } + } + @Override public int writeTask(Task task) { + checkDatabaseConfig(); int taskId = -1; + try (Connection conn = DriverManager.getConnection(url, username, password)) { conn.setAutoCommit(false); taskId = insertTask(conn, task); @@ -128,62 +144,67 @@ private void insertTaskTag(Connection conn, int taskId, int tagId) throws SQLExc } @Override - public List getAllTasks() { //TODO[#9]: Implement getAllTasks() to fetch in DB for all tasks. + public List getAllTasks() { + checkDatabaseConfig(); return List.of(); } -@Override -public Task getById(int id) { //Implement getById to fetch in DB for a task. - String sql = "SELECT task_id, description, priority, created_at, conclusion_at FROM TASKS WHERE task_id = ?"; - try (Connection conn = DriverManager.getConnection(url, username, password); - PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setInt(1, id); - try (ResultSet rs = stmt.executeQuery()) { - if (rs.next()) { - Task task = new Task(rs.getInt("task_id")); - task.setDescription(rs.getString("description")); - task.setPriority(Enum.valueOf(Priority.class, rs.getString("priority"))); - task.setCreation(rs.getTimestamp("created_at")); - Timestamp conclusion = rs.getTimestamp("conclusion_at"); - if (conclusion != null) { - task.setConclusion(conclusion); - } - // Fetch tags for this task - String tagSql = "SELECT t.name FROM TAGS t " + - "JOIN TASK_TAGS tt ON t.tag_id = tt.tag_id " + - "WHERE tt.task_id = ?"; - try (PreparedStatement tagStmt = conn.prepareStatement(tagSql)) { - tagStmt.setInt(1, id); - try (ResultSet tagRs = tagStmt.executeQuery()) { - List tags = new ArrayList<>(); - while (tagRs.next()) { - String tagName = tagRs.getString("name"); - try { - tags.add(Tag.valueOf(tagName)); - } catch (IllegalArgumentException e) { - LOGGER.warn("Unknown tag in DB: " + tagName); + @Override + public Task getById(int id) { + checkDatabaseConfig(); + String sql = "SELECT task_id, description, priority, created_at, conclusion_at FROM TASKS WHERE task_id = ?"; + try (Connection conn = DriverManager.getConnection(url, username, password); + PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, id); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + Task task = new Task(rs.getInt("task_id")); + task.setDescription(rs.getString("description")); + task.setPriority(Enum.valueOf(Priority.class, rs.getString("priority"))); + task.setCreation(rs.getTimestamp("created_at")); + Timestamp conclusion = rs.getTimestamp("conclusion_at"); + if (conclusion != null) { + task.setConclusion(conclusion); + } + // Fetch tags for this task + String tagSql = "SELECT t.name FROM TAGS t " + + "JOIN TASK_TAGS tt ON t.tag_id = tt.tag_id " + + "WHERE tt.task_id = ?"; + try (PreparedStatement tagStmt = conn.prepareStatement(tagSql)) { + tagStmt.setInt(1, id); + try (ResultSet tagRs = tagStmt.executeQuery()) { + List tags = new ArrayList<>(); + while (tagRs.next()) { + String tagName = tagRs.getString("name"); + try { + tags.add(Tag.valueOf(tagName)); + } catch (IllegalArgumentException e) { + LOGGER.warn("Unknown tag in DB: " + tagName); + } } + task.setTagList(tags); } - task.setTagList(tags); } + return task; } - return task; } + } catch (SQLException e) { + LOGGER.error(e.getMessage()); } - } catch (SQLException e) { - LOGGER.error(e.getMessage()); + return null; } - return null; -} @Override - public void update(int idFrom, Task taskFor) { //TODO[#11]: Implement update(int idFrom, Task taskFor) to update a task in DB. + public void update(int idFrom, Task taskFor) { + checkDatabaseConfig(); + //TODO[#11]: Implement update(int idFrom, Task taskFor) to update a task in DB. } @Override - public void removeById(int id) { //TODO[#12]: Implement removeById(int id) to delete a task by id in DB. + public void removeById(int id) { + checkDatabaseConfig(); + //TODO[#12]: Implement removeById(int id) to delete a task by id in DB. } } -