Class DmxHttpClient

java.lang.Object
dmx.fun.http.DmxHttpClient

@NullMarked public final class DmxHttpClient extends Object
A thin wrapper around HttpClient that returns Result<T, HttpError> instead of throwing exceptions.

Both network failures (IOException, InterruptedException) and HTTP error status codes (4xx, 5xx) are surfaced as typed HttpError variants, collapsing two separate failure modes into one:

DmxHttpClient client = DmxHttpClient.of(HttpClient.newHttpClient());

client.send(request, BodyHandlers.ofString())
    .peek(body -> process(body))
    .peekError(err -> log.warn("HTTP call failed: {}", err));

Limitation: null-body handlers are not supported

Body handlers that produce a null body — specifically HttpResponse.BodyHandlers.discarding() — are not supported. Result.ok() does not accept null values, so passing a null-body handler will throw NullPointerException on a successful response.

If you need to send a request and ignore the response body, use the plain HttpClient directly, or wait for a future sendDiscarding() overload.

  • Method Details

    • of

      public static DmxHttpClient of(HttpClient client)
      Creates a new DmxHttpClient wrapping the given HttpClient.
      Parameters:
      client - the underlying JDK HTTP client; must not be null
      Returns:
      a new DmxHttpClient
    • send

      public <T> Result<T, HttpError> send(HttpRequest request, HttpResponse.BodyHandler<T> bodyHandler)
      Sends an HTTP request synchronously and returns the result.

      Status mapping:

      Type Parameters:
      T - the body type
      Parameters:
      request - the request to send; must not be null
      bodyHandler - the response body handler; must not be null
      Returns:
      a Result wrapping the body or an HttpError
    • send

      public <T,R> Result<R, HttpError> send(HttpRequest request, HttpResponse.BodyHandler<T> bodyHandler, CheckedFunction<T,R> deserializer)
      Sends an HTTP request synchronously, then applies deserializer to the body.

      If the HTTP call succeeds but deserializer throws, the exception is wrapped in a HttpError.NetworkFailure.

      Type Parameters:
      T - the raw body type produced by bodyHandler
      R - the deserialized value type
      Parameters:
      request - the request to send; must not be null
      bodyHandler - the response body handler; must not be null
      deserializer - function applied to the raw body on success; must not be null
      Returns:
      a Result wrapping the deserialized value or an HttpError
    • sendAsync

      public <T> CompletableFuture<Result<T, HttpError>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> bodyHandler)
      Sends an HTTP request asynchronously and returns a CompletableFuture that completes with a Result.

      The returned future never completes exceptionally — transport failures are wrapped in HttpError.NetworkFailure or HttpError.Timeout.

      Type Parameters:
      T - the body type
      Parameters:
      request - the request to send; must not be null
      bodyHandler - the response body handler; must not be null
      Returns:
      a future that completes with a Result wrapping the body or an HttpError