Skip to content

Add HTTP client infrastructure with Java HttpClient and Jackson 3#25

Merged
rammrain merged 3 commits into
mainfrom
feature/http-client
Apr 10, 2026
Merged

Add HTTP client infrastructure with Java HttpClient and Jackson 3#25
rammrain merged 3 commits into
mainfrom
feature/http-client

Conversation

@rammrain
Copy link
Copy Markdown
Member

@rammrain rammrain commented Apr 10, 2026

Summary

  • Implements MontonioHttpClient in ee.bitweb.montonio.sdk.http wrapping java.net.http.HttpClient
  • Type-safe get() and post() methods with Jackson 3 JSON serialization/deserialization
  • Maps error responses to MontonioApiException (best-effort JSON field extraction), network failures to MontonioNetworkException

Test plan

  • Successful GET deserializes response body
  • Successful POST serializes request and deserializes response
  • Correct URI construction, headers, timeout, HTTP method
  • 4xx with JSON error body → MontonioApiException with parsed fields
  • 5xx with non-JSON body → MontonioApiException with raw body
  • Connection failure → MontonioNetworkException
  • Interrupted request → MontonioNetworkException + interrupt flag restored
  • Malformed JSON on 2xx → MontonioException
  • Null JSON fields in error response handled correctly
  • Full build passes with no deprecation warnings

Closes #11

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • HTTP client with JSON GET/POST, configurable timeouts and structured error handling.
  • Documentation

    • Added design document describing HTTP client behaviour, timeouts, error mapping and test strategy.
  • Chores

    • Added Jackson JSON runtime dependency to support serialization/deserialization.
  • Tests

    • Extensive unit tests covering request construction, JSON (de)serialization, error paths and network failures.

Implements internal HTTP client for Montonio API calls with GET/POST
support, JSON serialization via Jackson 3, and exception mapping for
error responses, network failures, and timeouts.

Closes #11

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d462edcd-912e-4b54-acdc-d6287602c7e6

📥 Commits

Reviewing files that changed from the base of the PR and between 331e223 and 3cc1ec1.

📒 Files selected for processing (1)
  • src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java

📝 Walkthrough

Walkthrough

Adds a new MontonioHttpClient implemented atop java.net.http.HttpClient with synchronous JSON GET/POST methods, Jackson 3 for (de)serialization, configurable timeouts and detailed error mapping; includes design documentation, unit tests, and a Jackson databind production dependency.

Changes

Cohort / File(s) Summary
Dependency Configuration
build.gradle
Added production dependency tools.jackson.core:jackson-databind:3.0.1 for JSON (de)serialization.
Design Documentation
docs/plans/2026-04-10-http-client-design.md
New design doc specifying MontonioHttpClient API, request/response shape, timeout and error-handling semantics, testing strategy and out-of-scope items.
HTTP Client Implementation
src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java
New public class wrapping java.net.http.HttpClient with get() and post() methods, header/timeout management, synchronous send, Jackson (ignore unknowns) (de)serialization, non-2xx error parsing into MontonioApiException, and network/deserialization exception mapping.
Unit Tests
src/test/java/ee/bitweb/montonio/sdk/http/MontonioHttpClientTest.java
New comprehensive JUnit 5 tests covering request construction, JSON serialization/deserialization, non-2xx error parsing (JSON and non-JSON), malformed JSON on 2xx, and network exceptions including interrupt handling.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant MontonioHttpClient
    participant JavaHttpClient as java.net.http.HttpClient
    participant RemoteAPI as Remote API

    Client->>MontonioHttpClient: get(path, responseType)
    MontonioHttpClient->>MontonioHttpClient: build URI (baseUrl + path), headers, timeout
    MontonioHttpClient->>JavaHttpClient: send(HttpRequest)
    JavaHttpClient->>RemoteAPI: HTTP request
    RemoteAPI-->>JavaHttpClient: HTTP response
    JavaHttpClient-->>MontonioHttpClient: HttpResponse

    alt Status 2xx
        MontonioHttpClient->>MontonioHttpClient: deserialize body -> responseType (Jackson)
        MontonioHttpClient-->>Client: return typed object
    else Status non-2xx
        MontonioHttpClient->>MontonioHttpClient: attempt parse error JSON (errorCode, message)
        MontonioHttpClient-->>Client: throw MontonioApiException
    else Network failure (IOException / InterruptedException)
        MontonioHttpClient-->>Client: throw MontonioNetworkException
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped along the baseUrl trail,
I pack JSON in each tiny mail,
GETs and POSTs with headers prim,
I parse the faults when lights go dim,
A rabbit client, steady and hale.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The implementation covers core requirements [#11]: wrapping java.net.http.HttpClient, supporting configurable timeouts, providing synchronous API, and including comprehensive unit tests. However, optional request/response logging and consumer-supplied HttpClient instance features are not implemented. Implement optional request/response logging functionality and ensure the public API explicitly supports consumer-supplied HttpClient injection at the SDK level, not just at the MontonioHttpClient constructor level.
Docstring Coverage ⚠️ Warning Docstring coverage is 1.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing HTTP client infrastructure with Java HttpClient and Jackson 3, which is the primary focus of all code changes in this pull request.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the HTTP client infrastructure implementation: build.gradle adds Jackson 3 dependency, documentation defines the design, MontonioHttpClient implements the client, and tests verify functionality. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/http-client

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/plans/2026-04-10-http-client-design.md`:
- Around line 106-108: The docs claim buildApiException always falls back to the
raw body as errorMessage when JSON is absent or missing fields, but the
implementation only uses the raw body when JSON parsing fails; if JSON parses
but lacks errorCode/message it returns null fields. Update buildApiException to
(1) wrap JSON parsing in try/catch to avoid throwing, (2) after parsing, verify
parsed.errorCode and parsed.message (or whatever fields are expected) and if
they are missing/null use the raw response body (or a default string like
"unknown error") for errorMessage and a default errorCode (e.g.,
"UNKNOWN_ERROR"), and (3) ensure the function always returns a usable exception
object rather than nulls so it matches the documentation.

In `@src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java`:
- Around line 23-38: The package-private constructor
MontonioHttpClient(MontonioSdkConfiguration configuration, HttpClient
httpClient) prevents consumers from supplying their own HttpClient and there's
no API to toggle request/response logging; make the injectable constructor
public so callers can pass a pre-configured java.net.http.HttpClient, and add a
visible hook to enable/disable logging (for example: a public boolean flag, a
LoggingLevel enum, or a Consumer<HttpRequest/HttpResponse> callback exposed via
constructor or a fluent MontonioHttpClientBuilder) that the client code checks
when sending requests to emit request/response details; update
MontonioHttpClient constructors (and/or introduce a public builder) to accept
both HttpClient and the logging toggle so shared pools/proxies/TLS customisation
and toggleable logging are available to SDK users.

In `@src/test/java/ee/bitweb/montonio/sdk/http/MontonioHttpClientTest.java`:
- Around line 98-105: The test postSerializesBodyAndDeserializesResponse doesn't
assert the outbound JSON; modify the StubHttpClient to capture the request body
(e.g., add a lastRequestBody/getLastRequestBody on StubHttpClient that stores
the raw request body passed into its request/send method) and then in
postSerializesBodyAndDeserializesResponse add an assertion that the captured
body equals the expected serialized JSON for new TestRequest("hello") (or
compare via the same serializer used by MontonioHttpClient to avoid string
formatting brittleness). Reference StubHttpClient, MontonioHttpClient,
postSerializesBodyAndDeserializesResponse, and TestRequest when adding the
capture and assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36df9596-f390-44ba-858f-d28ad55118b5

📥 Commits

Reviewing files that changed from the base of the PR and between dbe4b7e and 886c3c0.

📒 Files selected for processing (4)
  • build.gradle
  • docs/plans/2026-04-10-http-client-design.md
  • src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java
  • src/test/java/ee/bitweb/montonio/sdk/http/MontonioHttpClientTest.java

Comment thread docs/plans/2026-04-10-http-client-design.md Outdated
Comment thread src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java
Comment thread src/main/java/ee/bitweb/montonio/sdk/http/MontonioHttpClient.java
rammrain and others added 2 commits April 10, 2026 07:19
Fix design doc to accurately describe null field behavior in error
parsing. Add request body assertion to POST test to verify outbound
JSON serialization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rammrain rammrain merged commit d539078 into main Apr 10, 2026
5 checks passed
@rammrain rammrain deleted the feature/http-client branch April 10, 2026 07:38
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.

HTTP client infrastructure with Java HttpClient

1 participant