Skip to content

9 спринт. 1-коммит.#8

Open
Georgiy2803 wants to merge 6 commits intomainfrom
sprint_9-solution-http-api
Open

9 спринт. 1-коммит.#8
Georgiy2803 wants to merge 6 commits intomainfrom
sprint_9-solution-http-api

Conversation

@Georgiy2803
Copy link
Copy Markdown
Owner

@Georgiy2803 Georgiy2803 commented Jul 16, 2025

Summary by Sourcery

Set up a full HTTP-based interface for the task management system with Gson-backed handlers and adapters, streamline CSV time parsing, add comprehensive integration tests for all endpoints, and include demo code in Main.java

New Features:

  • Provide HTTP API endpoints for task, epic, and subtask management plus history and prioritized task retrieval
  • Implement HttpTaskServer with dedicated handlers for tasks, epics, subtasks, history, and prioritized tasks using Gson serialization
  • Introduce Gson TypeAdapters for Duration and LocalDateTime

Enhancements:

  • Refactor CsvConverter to centralize time parsing into stringToDate and stringToDuration methods

Tests:

  • Add JUnit integration tests for all API handlers (tasks, epics, subtasks, history, prioritized)
  • Include HttpTaskServerConfigTest to verify server startup and endpoint accessibility

Chores:

  • Populate Main.java with commented examples demonstrating InMemoryTaskManager usage

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Jul 16, 2025

Reviewer's Guide

This PR adds a full HTTP API layer to the task manager (with server, handlers and JSON adapters) and coverage tests, refactors CSV conversion logic, and extends the Main class with manual in-memory/file-backed manager scenarios.

Sequence diagram for HTTP request handling in TaskHandler

sequenceDiagram
    actor Client
    participant HttpTaskServer
    participant TaskHandler
    participant TaskManager
    participant Gson
    Client->>HttpTaskServer: HTTP request (e.g. POST /tasks)
    HttpTaskServer->>TaskHandler: handle(exchange)
    TaskHandler->>Gson: Parse request body (fromJson)
    TaskHandler->>TaskManager: createTask(task)
    TaskManager-->>TaskHandler: Task created
    TaskHandler->>Gson: Serialize response (toJson)
    TaskHandler->>Client: HTTP response
Loading

Class diagram for new HTTP API handlers and adapters

classDiagram
    class BaseHttpHandler {
        - TaskManager taskManager
        - Gson gson
        + sendText()
        + sendOk()
        + sendBadRequest()
        + sendNotFound()
        + sendHasInteractions()
        + sendCreated()
        + sendInternalServerError()
        + sendMethodNotAllowed()
        + searchIdTask()
    }
    class TaskHandler {
        + handle()
        + handleGetTasks()
        + handleGetTaskById()
        + handleCreateTask()
        + handleDeleteTask()
    }
    class SubtaskHandler {
        + handle()
        + handleGetSubtasks()
        + handleGetSubtaskId()
        + handleCreateSubtask()
        + handleDeleteSubtask()
    }
    class EpicHandler {
        + handle()
        + handleGetEpics()
        + handleGetEpicId()
        + handleGetEpicSubtasks()
        + handleCreateEpic()
        + handleDeleteEpic()
    }
    class HistoryHandler {
        + handle()
    }
    class PrioritizedHandler {
        + handle()
    }
    class DurationAdapter {
        + write()
        + read()
    }
    class LocalDateTimeAdapter {
        + write()
        + read()
    }
    TaskHandler --|> BaseHttpHandler
    SubtaskHandler --|> BaseHttpHandler
    EpicHandler --|> BaseHttpHandler
    HistoryHandler --|> BaseHttpHandler
    PrioritizedHandler --|> BaseHttpHandler
Loading

Class diagram for updated CsvConverter time processing

classDiagram
    class CsvConverter {
        + processingTimeForTask(Task, String, String)
        + processingTimeForEpic(Epic, String)
        + stringToDate(String)
        + stringToDuration(String)
        - isNoData(String)
    }
    CsvConverter ..> Task
    CsvConverter ..> Epic
Loading

File-Level Changes

Change Details Files
Implemented HTTP server and request routing for task management
  • Initialized HttpTaskServer with endpoints for tasks, epics, subtasks, history and prioritized
  • Created BaseHttpHandler for common HTTP response handling
  • Developed TaskHandler, EpicHandler, SubtaskHandler, HistoryHandler, PrioritizedHandler to process CRUD operations
src/main/api/HttpTaskServer.java
src/main/api/handler/BaseHttpHandler.java
src/main/api/handler/TaskHandler.java
src/main/api/handler/EpicHandler.java
src/main/api/handler/SubtaskHandler.java
src/main/api/handler/HistoryHandler.java
src/main/api/handler/PrioritizedHandler.java
Added JSON adapters for custom types
  • Registered Gson TypeAdapters for Duration and LocalDateTime
  • Implemented serialization/deserialization logic in adapters
src/main/api/adapter/DurationAdapter.java
src/main/api/adapter/LocalDateTimeAdapter.java
Introduced comprehensive API integration tests
  • Added handler tests for tasks, epics, subtasks covering create/update/get/delete and edge cases
  • Added tests for prioritized list and history endpoints
  • Included server configuration sanity checks
src/test/apiTest/handlerTest/TasksHandlerTest.java
src/test/apiTest/handlerTest/EpicsHandlerTest.java
src/test/apiTest/handlerTest/SubtasksHandlerTest.java
src/test/apiTest/handlerTest/PrioritizedHandlerTest.java
src/test/apiTest/handlerTest/HistoryHandlerTest.java
src/test/apiTest/HttpTaskServerConfigTest.java
Refactored CSV conversion utility
  • Extracted stringToDate and stringToDuration helpers
  • Simplified processingTimeForTask and processingTimeForEpic to delegate to helpers
src/main/managers/file/CsvConverter.java
Extended Main.java with manual test scenarios
  • Added commented blocks demonstrating default and file-backed manager flows
  • Initialized InMemoryTaskManager usage with various task/epic/subtask operations
src/main/Main.java

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @Georgiy2803 - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Missing break statements in switch may cause fall-through. (link)

General comments:

  • Main.java contains huge commented-out blocks—please remove or relocate example code into proper tests or demos to keep the entry point clean.
  • EpicHandler.handle() is missing break statements in its switch, resulting in unintended fall-through; add breaks to ensure only the correct endpoint logic runs.
  • HttpTaskServer.main() starts and then immediately stops the server—remove the premature stopServer() call so the server stays running as expected.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Main.java contains huge commented-out blocks—please remove or relocate example code into proper tests or demos to keep the entry point clean.
- EpicHandler.handle() is missing break statements in its switch, resulting in unintended fall-through; add breaks to ensure only the correct endpoint logic runs.
- HttpTaskServer.main() starts and then immediately stops the server—remove the premature stopServer() call so the server stays running as expected.

## Individual Comments

### Comment 1
<location> `src/main/api/handler/EpicHandler.java:27` </location>
<code_context>
+    public void handle(HttpExchange exchange) throws IOException {
+        Endpoint endpoint = getEndpoint(exchange.getRequestURI(), exchange.getRequestMethod());
+
+        switch (endpoint) {
+            case GET_EPIC:
+                handleGetEpicId(exchange);
+            case GET_EPICS:
+                handleGetEpics(exchange);
+            case GET_EPIC_SUBTASKS:
+                handleGetEpicSubtasks(exchange);
+            case POST_EPIC:
+                handleCreateEpic(exchange);
+            case DELETE_EPIC:
+                handleDeleteEpic(exchange);
+            case UNKNOWN:
+                sendMethodNotAllowed(exchange);
+        }
</code_context>

<issue_to_address>
Missing break statements in switch may cause fall-through.

The switch cases in handle() lack break statements, causing all subsequent handlers to execute after a match. This can lead to multiple responses for one request.
</issue_to_address>

### Comment 2
<location> `src/main/api/adapter/DurationAdapter.java:26` </location>
<code_context>
+    }
+
+    @Override
+    public Duration read(final JsonReader jsonReader) throws IOException {
+            long minutes = Long.parseLong(jsonReader.nextString());
+            return Duration.ofMinutes(minutes);
+    }
+}
</code_context>

<issue_to_address>
No handling for empty or invalid input in read().

Consider adding error handling for cases where nextString() returns an empty or invalid value, such as returning null or throwing a custom exception, to prevent runtime errors.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
    @Override
    public Duration read(final JsonReader jsonReader) throws IOException {
            long minutes = Long.parseLong(jsonReader.nextString());
            return Duration.ofMinutes(minutes);
    }
=======
    @Override
    public Duration read(final JsonReader jsonReader) throws IOException {
        String value = jsonReader.nextString();
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            long minutes = Long.parseLong(value);
            return Duration.ofMinutes(minutes);
        } catch (NumberFormatException e) {
            // Optionally, you could throw a custom exception here instead of returning null
            return null;
        }
    }
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `src/main/api/adapter/LocalDateTimeAdapter.java:33` </location>
<code_context>
+    }
+
+    @Override
+    public LocalDateTime read(final JsonReader jsonReader) throws IOException {
+        String startTimeStr = jsonReader.nextString();
+        if (!startTimeStr.isEmpty()) {
+            return LocalDateTime.parse(startTimeStr, dtf);
+        }
+        return null;
+    }
+
</code_context>

<issue_to_address>
No error handling for invalid date format in read().

Add error handling to manage exceptions from LocalDateTime.parse() when input does not match the expected format.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
    @Override
    public LocalDateTime read(final JsonReader jsonReader) throws IOException {
        String startTimeStr = jsonReader.nextString();
        if (!startTimeStr.isEmpty()) {
            return LocalDateTime.parse(startTimeStr, dtf);
        }
        return null;
    }
=======
    @Override
    public LocalDateTime read(final JsonReader jsonReader) throws IOException {
        String startTimeStr = jsonReader.nextString();
        if (!startTimeStr.isEmpty()) {
            try {
                return LocalDateTime.parse(startTimeStr, dtf);
            } catch (Exception e) {
                throw new IOException("Invalid date format for LocalDateTime: " + startTimeStr, e);
            }
        }
        return null;
    }
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/main/api/handler/EpicHandler.java Outdated
Comment on lines +27 to +40
switch (endpoint) {
case GET_EPIC:
handleGetEpicId(exchange);
case GET_EPICS:
handleGetEpics(exchange);
case GET_EPIC_SUBTASKS:
handleGetEpicSubtasks(exchange);
case POST_EPIC:
handleCreateEpic(exchange);
case DELETE_EPIC:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Missing break statements in switch may cause fall-through.

The switch cases in handle() lack break statements, causing all subsequent handlers to execute after a match. This can lead to multiple responses for one request.

Comment on lines +25 to +29
@Override
public Duration read(final JsonReader jsonReader) throws IOException {
long minutes = Long.parseLong(jsonReader.nextString());
return Duration.ofMinutes(minutes);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: No handling for empty or invalid input in read().

Consider adding error handling for cases where nextString() returns an empty or invalid value, such as returning null or throwing a custom exception, to prevent runtime errors.

Suggested change
@Override
public Duration read(final JsonReader jsonReader) throws IOException {
long minutes = Long.parseLong(jsonReader.nextString());
return Duration.ofMinutes(minutes);
}
@Override
public Duration read(final JsonReader jsonReader) throws IOException {
String value = jsonReader.nextString();
if (value == null || value.trim().isEmpty()) {
return null;
}
try {
long minutes = Long.parseLong(value);
return Duration.ofMinutes(minutes);
} catch (NumberFormatException e) {
// Optionally, you could throw a custom exception here instead of returning null
return null;
}
}

Comment on lines +32 to +34
@Override
public LocalDateTime read(final JsonReader jsonReader) throws IOException {
String startTimeStr = jsonReader.nextString();
if (!startTimeStr.isEmpty()) {
return LocalDateTime.parse(startTimeStr, dtf);
}
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): No error handling for invalid date format in read().

Add error handling to manage exceptions from LocalDateTime.parse() when input does not match the expected format.

Suggested change
@Override
public LocalDateTime read(final JsonReader jsonReader) throws IOException {
String startTimeStr = jsonReader.nextString();
if (!startTimeStr.isEmpty()) {
return LocalDateTime.parse(startTimeStr, dtf);
}
return null;
}
@Override
public LocalDateTime read(final JsonReader jsonReader) throws IOException {
String startTimeStr = jsonReader.nextString();
if (!startTimeStr.isEmpty()) {
try {
return LocalDateTime.parse(startTimeStr, dtf);
} catch (Exception e) {
throw new IOException("Invalid date format for LocalDateTime: " + startTimeStr, e);
}
}
return null;
}

@Georgiy2803 Georgiy2803 force-pushed the sprint_9-solution-http-api branch from cc1b7f6 to d3ae0bf Compare July 16, 2025 18:01
@Georgiy2803 Georgiy2803 force-pushed the sprint_9-solution-http-api branch from d3ae0bf to cc5ff91 Compare July 16, 2025 18:04
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