Skip to content

Technical Reference

Technical reference for the aem-http-foundation.core OSGi bundle: architecture, public API, configuration model, and runtime boundaries.

This page is intentionally reference-oriented.
If you are onboarding a project, start with:


Compatibility

Component Version / Details
AEM AEM as a Cloud Service
Java Compiled to Java 11 bytecode; runs on Java 11 and Java 21
Apache HttpClient 4.5.x, supplied by the AEM runtime via HttpClientBuilderFactory

What this bundle is for

The core bundle standardizes outbound HTTP infrastructure for AEMaaCS.

It provides a shared foundation for:

  • pooled outbound CloseableHttpClient instances
  • timeout and retry configuration
  • TLS and trust-store integration
  • optional authentication layering
  • optional Adobe-specific request customization

It is designed to centralize the repeating transport and auth-related mechanics of outbound integrations, while leaving API-specific logic in the consuming bundle.


Overview

Goal Use
Plain pooled CloseableHttpClient for any outbound call HttpClientProvider
Adobe API integration with OAuth + Adobe gateway headers AdobeIntegrationConfiguration
Multiple integrations intentionally sharing one credential set OAuthClientCredentialsTokenSupplier + bearer customization
Generic OAuth client_credentials against any RFC 6749 issuer OAuthClientCredentialsTokenSupplier + bearer customization
Custom auth scheme implement HttpClientCustomizer and pass it to HttpClientProvider.provide(...)

Configuration model

The foundation uses three configuration layers:

  • Shared HTTP defaultsHttpConfigService / HttpConfig: timeouts, pool sizing, retry behavior
  • Optional shared OAuth credentialsOAuthClientCredentialsTokenSupplier: reusable credential sets shared across multiple integrations; advanced, not the default path
  • Integration-specific request policiesAdobeIntegrationConfiguration: bearer token injection, Adobe headers, per-integration client customization

Architecture

Outbound HTTP calls are keyed and pooled:

  • HttpClientProvider creates or retrieves a CloseableHttpClient per logical key
  • HttpConfigService supplies timeout, pool, and retry settings from OSGi metatype
  • Authentication is layered on top in three clearly separated packages:
  • auth.oauth — generic OAuth 2.0 client_credentials
  • auth.bearer — generic Authorization: Bearer ... request enrichment
  • auth.adobe — Adobe-specific gateway headers and AdobeIntegrationConfiguration
┌───────────────────────────┐   ┌───────────────────────────────┐
│   HttpClientProvider      │   │      HttpConfigService        │
│   (public interface)      │   │      (public interface)       │
└────────────┬──────────────┘   └──────────────┬────────────────┘
             │                                 │
┌────────────▼──────────────┐   ┌──────────────▼────────────────┐
│  HttpClientProviderImpl   │───│   HttpConfigServiceImpl       │
│  · pooling / cache        │   │   OSGi metatype → HttpConfig  │
│  · TLS / trust handling   │   └───────────────────────────────┘
│  · retry handlers         │
└────────────┬──────────────┘
             │ optional composition via HttpClientCustomizer
┌────────────▼─────────────────────────────────────────────────────────┐
│  AdobeIntegrationConfiguration                                       │
│  · HttpClientCustomizer                                              │
│  · AccessTokenSupplier                                               │
│  · bearer auth                                                       │
│  · x-api-key                                                         │
│  · x-gw-ims-org-id                                                   │
└────────────┬─────────────────────────────────────────────────────────┘
             │ delegates token acquisition and caching
┌────────────▼─────────────────────────────────────────────────────────┐
│  CachingTokenAcquirer                                                │
│  · OAuth client_credentials acquisition                              │
│  · cache and refresh before expiry                                   │
└──────────────────────────────────────────────────────────────────────┘

Public contract vs internal implementation

Singleton services - inject via @Reference

Factory components - one config file per integration context

Internal implementation


Lifecycle guarantees

The foundation manages the lifecycle of pooled clients.

Guaranteed behavior

  • clients are pooled and cached by logical key
  • the same logical key resolves to the same pooled client context
  • client lifecycle is managed by the foundation
  • pools and connection managers are shut down when the owning bundle deactivates

Consumer responsibilities

  • do not call close() on pooled CloseableHttpClient instances returned by the foundation
  • do close each CloseableHttpResponse
  • choose logical keys that reflect an integration or policy context, not just a single URL

This separation keeps pooling and shutdown behavior predictable.


Public interfaces

HttpClientProvider

Primary entry point for creating or retrieving pooled CloseableHttpClient instances by logical key.

Use this when you want:

  • a shared client per integration key
  • central lifecycle management
  • optional per-client builder customization

Typical usage:

CloseableHttpClient client = httpClientProvider.provide("orders-api");

or with a customizer and default config:

CloseableHttpClient client = httpClientProvider.provide(
    "orders-api",
    builder -> builder.addInterceptorLast(myInterceptor)
);

or with explicit config and customizer:

CloseableHttpClient client = httpClientProvider.provide(
    "orders-api",
    customConfig,
    builder -> builder.addInterceptorLast(myInterceptor)
);

HttpConfigService

Provides the effective HttpConfig derived from OSGi configuration.

Use this when:

  • you need to derive a per-integration override
  • you want to inspect foundation defaults

HttpClientCustomizer

Extension point for mutating the Apache HttpClientBuilder used by the provider.

Typical uses:

  • request interceptors
  • auth layers
  • additional headers
  • integration-specific builder behavior

AccessTokenSupplier and AccessToken

Abstraction for components that can provide access tokens.

In practice this is used by:

  • generic OAuth token suppliers
  • Adobe integration configurations that also expose token supply

Use this when you need raw token access, not only automatic request customization.


Public data objects

HttpConfig

Immutable configuration object describing the effective HTTP settings used by the foundation. All time-valued fields are expressed in milliseconds.

OSGi configuration

  • PID: org.kttn.aem.http.impl.HttpConfigServiceImpl (singleton — not a factory)
/apps/myapp/config/org.kttn.aem.http.impl.HttpConfigServiceImpl.cfg.json

Field reference

Property Required Default Meaning
http.config.connectionTimeout no 10000 TCP connect timeout to the remote host (milliseconds). Maps to Apache HttpClient RequestConfig#setConnectTimeout.
http.config.connectionManagerTimeout no 10000 Maximum time to wait when leasing a pooled connection (milliseconds). Maps to RequestConfig#setConnectionRequestTimeout.
http.config.socketTimeout no 10000 Socket read/write timeout (SO_TIMEOUT) in milliseconds; 0 means infinite. Maps to RequestConfig#setSocketTimeout.
http.config.maxConnection no 100 Upper bound on total concurrent connections in the pool. Maps to PoolingHttpClientConnectionManager#setMaxTotal.
http.config.maxConnectionPerRoute no 20 Upper bound on concurrent connections per HTTP route (host + scheme + port). Maps to PoolingHttpClientConnectionManager#setDefaultMaxPerRoute.
http.config.serviceUnavailableMaxRetryCount no 3 Maximum retries after an HTTP 503 response; 0 disables this retry path.
http.config.serviceUnavailableRetryInterval no 1000 Delay in milliseconds between subsequent 503 retries (applied after the first attempt).
http.config.ioExceptionMaxRetryCount no 3 Maximum retries after a retriable java.io.IOException; 0 disables.
http.config.ioExceptionRetryInterval no 1000 Delay in milliseconds between subsequent I/O retries (applied after the first attempt).

Per-integration override

See EXAMPLES.md → Example 4 for the pattern.


Authentication components

AdobeIntegrationConfiguration

Factory component for Adobe server-to-server integration contexts.

OSGi configuration

  • Factory PID: org.kttn.aem.http.auth.adobe.impl.AdobeIntegrationConfiguration (one configuration file per integration)
  • Example path: /apps/myapp/config/org.kttn.aem.http.auth.adobe.impl.AdobeIntegrationConfiguration~aio-runtime-prod.cfg.json
  • Inject a specific instance with an LDAP-style target filter (OSGi service filter syntax) on service.pid, for example (service.pid=org.kttn.aem.http.auth.adobe.impl.AdobeIntegrationConfiguration~aio-runtime-prod).
  • Multi-value properties are string arrays in .cfg.json (for example "additional.headers": ["x-sandbox-name=prod"]).

Field reference

Property Required Default Meaning
credential.id no (empty) When set, bearer tokens come from the shared OAuthClientCredentialsTokenSupplier with the same credential.id; inline token fields below are ignored for acquisition.
clientId yes* (empty) OAuth client ID; required for inline mode. With credential.id set, optional: overrides x-api-key only; if omitted there, the value is read from the shared supplier clientId property.
clientSecret yes* (empty) OAuth client secret; required when credential.id is empty; ignored when shared credentials are used.
scopes no (empty) Comma-separated OAuth scopes (inline mode only).
set.api.key.header no true When true, sends x-api-key using clientId or, in shared mode, the shared supplier clientId property if local clientId is blank.
org.id.header.value no (empty) Value for the x-gw-ims-org-id header on API requests (not sent to the token endpoint).
tokenEndpointUrl no https://ims-na1.adobelogin.com/ims/token/v3 Token endpoint (inline mode only).
additional.token.params no (empty) Advanced: extra token POST form fields as name=value entries (inline mode only).
additional.headers no (empty) Advanced: extra static request headers as name=value entries.
  • required when credential.id is empty.

Responsibilities include:

  • bearer token request customization
  • optional Adobe API key header
  • optional Adobe org id header
  • inline or shared credential usage (shared tokens via OAuthClientCredentialsTokenSupplier + credential.id)
  • token caching through the internal token acquirer

OAuthClientCredentialsTokenSupplier

Generic OAuth 2.0 client_credentials supplier for non-Adobe and shared-credential use cases.

OSGi configuration

  • Factory PID: org.kttn.aem.http.auth.oauth.impl.OAuthClientCredentialsTokenSupplier (one file per logical credential set)
  • Example path: /apps/myapp/config/org.kttn.aem.http.auth.oauth.impl.OAuthClientCredentialsTokenSupplier~aep-prod.cfg.json
  • Optional LDAP-style filter (OSGi service filter) on shared suppliers: (credential.id=<your-id>) (must match credential.id on AdobeIntegrationConfiguration when using Example 3).

Field reference

Property Required Default Meaning
credential.id no (empty) Logical id exposed as the credential.id service property for Adobe integrations to reference.
clientId yes OAuth client_id (token request and service property for shared x-api-key).
clientSecret yes OAuth client_secret; use $[secret:…] in AEMaaCS where possible.
scopes no (empty) Comma-separated scopes; empty omits the scope parameter.
tokenEndpointUrl no https://ims-na1.adobelogin.com/ims/token/v3 OAuth 2.0 token endpoint.

Design decisions

Hybrid trust manager

The foundation can combine:

  • JVM default trust material
  • optional Granite trust-store material

This allows projects to preserve standard public CA behavior while also trusting project-specific certificates managed in AEM.

Key-based client cache

Clients are cached by logical key rather than by URL.

That is deliberate:

  • one integration may call multiple URLs
  • the key models the client or policy context, not a single endpoint
  • connection reuse and lifecycle are easier to reason about this way

Layered auth packages

The bundle separates:

  • generic OAuth token acquisition
  • generic bearer request enrichment
  • Adobe-specific request behavior

This keeps the core transport layer reusable while avoiding Adobe-specific assumptions in generic OAuth support.


Non-goals

To keep the foundation focused, the following are intentionally out of scope:

  • user-based OAuth flows such as Authorization Code or PKCE
  • refresh-token workflows for user clients
  • generic identity-provider integration beyond OAuth client_credentials
  • product-specific API facades
  • a universal abstraction over every Adobe or AEM endpoint
  • automatic “service profiles” that hide what auth or headers are being applied

Usage examples

Example Level When to use it
Example 1 — Public REST API Basic Plain pooled outbound HTTP with no special authentication; recommended first smoke test after deployment.
Example 2 — Adobe integration Recommended Recommended default for Adobe server-to-server APIs (IMS OAuth client_credentials, optional Adobe headers).
Example 3 — Custom Basic Auth Intermediate Non-OAuth endpoints that use Basic authentication, while still reusing the foundation's pooled client lifecycle.
Example 4 — Custom timeouts per integration Intermediate One integration needs different timeouts than the shared defaults, without loosening them globally.
Example 5 — Shared credentials across multiple integrations Advanced Multiple Adobe integrations intentionally share one OAuth credential set but keep separate integration contexts.

See also

  • Integration — choosing the right integration path
  • Examples — concrete usage patterns for common scenarios