Skip to content

Implement a new HTTP Client Abstraction/Facade with an Apache Commons HTTP Client 5 module #5723

@aschwarte10

Description

@aschwarte10

Problem description

Problem

The RDF4J HTTP client stack (rdf4j-http-client) is tightly coupled to Apache HttpComponents 4 (AHC4). AHC4 types appear directly in public APIs:

  • HttpClientDependent#getHttpClient() / #setHttpClient() — typed to org.apache.http.client.HttpClient
  • HttpClientSessionManager#getHttpClient() — same

This makes it impossible for users to substitute a different HTTP client without patching RDF4J internals, and forces an AHC4 transitive dependency on all RDF4J HTTP users.

Proposed Solution

Introduce a thin, zero-third-party-dependency SPI layer (rdf4j-http-client-api) and ship two pluggable implementations:

  • rdf4j-http-client-jdk — backed by java.net.http.HttpClient (JDK 11+, zero additional dependencies, default)
  • rdf4j-http-client-apache5 — backed by Apache HttpComponents 5 (opt-in for advanced connection management)

Implementations are discovered via ServiceLoader. The active factory can be selected via the system property rdf4j.http.client.factory.

New module structure

core/http/
├── client-api/ (NEW) — SPI interfaces, no HTTP library dependency
├── client-jdk/ (NEW) — JDK java.net.http implementation
├── client-apache5/ (NEW) — Apache HC5 implementation
└── client/ (refactored) — SPARQLProtocolSession etc., depends on client-api only

Core SPI types (org.eclipse.rdf4j.http.client.spi)

Type Role
RDF4JHttpClient Central execution interface; execute(HttpClientRequest) → HttpClientResponse
HttpClientRequest Immutable request value object (method, URI, headers, optional body)
HttpClientResponse Response with status, headers, streaming body; must be closed
HttpClientRequestBody Body abstraction with convenience factories (form data, string, bytes, stream)
HttpClientConfig Timeouts, connection pool limits, redirect policy, TLS
HttpAuthConfig / BasicHttpAuthConfig Authentication configuration (extensible)
RDF4JHttpClientFactory SPI for creating clients; registered via ServiceLoader
RDF4JHttpClients Utility for obtaining the default or named factory

Refactoring scope

  • HttpClientDependent and HttpClientSessionManager updated to expose RDF4JHttpClient instead of AHC4 types
  • SPARQLProtocolSession and RDF4JProtocolSession rewritten to use RDF4JHttpClient exclusively
  • SharedHttpClientSessionManager updated to use RDF4JHttpClientFactory
  • All existing system properties preserved (mapped to HttpClientConfig fields)
  • AHC4 dependency removed from rdf4j-http-client entirely

Breaking Change

This is a hard break from AHC4 — no compatibility bridge. Users who inject a custom HttpClient or cast getHttpClient() to an AHC4 type must migrate:

Current Migration
repo.setHttpClient(myApacheHC4Client) Build an RDF4JHttpClient via RDF4JHttpClients factory
(CloseableHttpClient) repo.getHttpClient() Use repo.getHttpClient() typed as RDF4JHttpClient
Custom HttpClientSessionManager impl Update to new interface signature
Implicit AHC4 transitive dependency Add rdf4j-http-client-apache5 explicitly if AHC5 is desired

Implementation Checklist

  • Create rdf4j-http-client-api with all SPI interfaces and value types
  • Create rdf4j-http-client-jdk (JDK 11+ implementation)
  • Create rdf4j-http-client-apache5 (AHC5 implementation)
  • Refactor SPARQLProtocolSession and RDF4JProtocolSession
  • Refactor SharedHttpClientSessionManager
  • Update HttpClientDependent and HttpClientSessionManager interfaces
  • Remove AHC4 from rdf4j-http-client pom.xml
  • Update migration guide / changelog

Preferred solution

No response

Are you interested in contributing a solution yourself?

None

Alternatives you've considered

No response

Anything else?

No response

Metadata

Metadata

Assignees

Labels

M1Fixed in milestone 1📶 enhancementissue is a new feature or improvement

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions