HomeIntegrations & Platform Patterns › Calling external APIs from AEM

Calling external APIs from AEM

Purpose: The standard shape for outbound HTTP: a configured OSGi service using a managed HttpClient.

Who this page is for

AudienceWhy it matters to you
Backend engineersThe template for every outbound call

The standard shape

One OSGi service per upstream system, wrapping a shared, pooled Apache HttpClient, with endpoint/timeout config per run mode:

@Component(service = RatingClient.class)
@Designate(ocd = RatingClient.Config.class)
public class RatingClient {
    @ObjectClassDefinition interface Config {
        @AttributeDefinition String endpoint();
        @AttributeDefinition int timeoutMs() default 800;
    }

    private CloseableHttpClient http;
    private Config cfg;

    @Activate void activate(Config cfg) {
        this.cfg = cfg;
        this.http = HttpClients.custom()
            .setConnectionManager(pooled(20))
            .setDefaultRequestConfig(RequestConfig.custom()
                .setConnectTimeout(cfg.timeoutMs())
                .setSocketTimeout(cfg.timeoutMs()).build())
            .build();
    }
    @Deactivate void deactivate() throws IOException { http.close(); }

    public Optional<Quote> quote(String planId) { /* GET, map, catch, Optional.empty() on failure */ }
}

Non-negotiables

RuleWhy
Connect + socket timeouts always setDefault is effectively infinite; one hung upstream exhausts render threads
Pooled connection manager, sized deliberatelyPer-request clients leak sockets
Return Optional/fallback, never throw into HTLPages must render through outages
Endpoint per run mode (ui.config)dev hits mocks, prod hits prod
Auth via secrets mechanismNot in code, not in repo config (secrets)
Log with correlation ID, no payload PIIDebuggability without leakage

Where calls may run

ContextVerdict
Scheduled job / Sling job✔ ideal — async, retryable
Servlet handling an explicit AJAX request✔ with timeouts — user asked for live data
Sling Model during page render⚠ only with cache + tight timeout + fallback; prefer avoiding
Workflow process step✔ (async by nature)
Event listener thread✗ enqueue a job instead

Quick navigation