Class AbstractRequestExecutor<T extends AbstractRequestExecutor<T>>

java.lang.Object
net.ygbstudio.jbrave.core.executors.AbstractRequestExecutor<T>
Type Parameters:
T - the concrete subclass type, used to support fluent builder-style APIs
Direct Known Subclasses:
BraveRequestExecutor

public abstract class AbstractRequestExecutor<T extends AbstractRequestExecutor<T>> extends Object
Base class for executing HTTP requests using a shared, long-lived HttpClient.

This executor is designed to be extended by concrete request builders or clients. It provides a consistent execution model that:

  • Uses a single, reusable HttpClient instance
  • Fully consumes HTTP responses using a byte[] body handler
  • Performs response decompression and decoding after transport completion
  • Adapts the result into an HttpResponse with a transformed body

Lifecycle and resource management: This class intentionally reuses a single HttpClient instance for its entire lifetime. The client is not closed per request. Connection pooling, HTTP/2 multiplexing, and cleanup are managed internally by the JDK HTTP client implementation.

If callers require explicit control over the HttpClient lifecycle or configuration, they should manage their own client instance externally and use the request builders provided by JBrave to construct HttpRequest and URI instances.

Builders in the api package are designed to be independent of any specific HTTP client implementation.

  • Field Details

  • Constructor Details

    • AbstractRequestExecutor

      public AbstractRequestExecutor()
  • Method Details

    • self

      protected T self()
      Returns the current instance cast to the concrete subclass type.

      This method supports fluent APIs in subclasses by avoiding repeated casts. The cast is safe by construction because the type parameter T is constrained to extend AbstractRequestExecutor<T>.

      Returns:
      this instance, cast to T
    • decompressGunzip

      protected byte[] decompressGunzip(byte[] compressedBytes) throws IOException
      Decompresses a GZIP-compressed byte array.

      This method performs a bounded, in-memory decompression of the provided byte array. It should be used only after the full response body has been received.

      Parameters:
      compressedBytes - the GZIP-compressed data
      Returns:
      the decompressed bytes
      Throws:
      IOException - if the compressed data is malformed or decompression fails
    • decodeByteArray

      protected String decodeByteArray(byte[] bytes, Charset charset)
      Decodes a byte array into a String using the given character set.

      The character set must be provided explicitly to avoid reliance on platform default encodings.

      Parameters:
      bytes - the raw byte data
      charset - the character set to use for decoding
      Returns:
      the decoded string
    • decodeByteHttpResponse

      protected String decodeByteHttpResponse(HttpResponse<byte[]> byteResponse)
      Decodes an HttpResponse with a byte[] body into a String.

      If the response indicates GZIP compression, the body is decompressed before decoding. Decoding assumes UTF-8 encoding, as response bodies are expected to represent textual content such as JSON or other UTF-8 encoded payloads intended for deserialization into domain objects.

      This method performs all transformations eagerly and should be invoked only after the HTTP response has been fully received.

      Parameters:
      byteResponse - the HTTP response containing a byte array body
      Returns:
      the decoded response body as a string
      Throws:
      ResponseDecompressionException - if decompression fails
    • adaptHttpResponse

      protected <R, U> HttpResponse<U> adaptHttpResponse(HttpResponse<R> httpResponse, U newResponseBody)
      Adapts an existing HttpResponse to a new response body type.

      The returned response delegates all metadata (status code, headers, request, URI, protocol version, etc.) to the original response while exposing the provided body value.

      This adapter does not preserve redirect history; HttpResponse.previousResponse() always returns Optional.empty(), regardless of whether redirects occurred during request execution.

      This is a structural adaptation only; no additional HTTP processing occurs.

      Type Parameters:
      R - the original response body type
      U - the adapted response body type
      Parameters:
      httpResponse - the original HTTP response
      newResponseBody - the transformed response body
      Returns:
      an HttpResponse exposing the transformed body
    • execute

      @NotNull public final @NotNull HttpResponse<String> execute(HttpRequest request) throws InterruptedException
      Executes the given HTTP request and returns a decoded response.

      The request is sent using the shared HttpClient. The response body is fully materialized as a byte[] before any transformation occurs.

      If the response is GZIP-compressed, it is decompressed and then decoded into a String. The resulting body is adapted into a new HttpResponse instance.

      This method performs no streaming and does not expose partially received data.

      Parameters:
      request - the HTTP request to execute
      Returns:
      an HttpResponse containing the decoded response body
      Throws:
      InterruptedException - if the executing thread is interrupted
      BraveClientException - if request execution or response processing fails