All AEM as a Cloud Service skills: component development, Workflow model design, development, triggering, launchers, debugging, and triaging, Dispatcher config authoring, advisory, incident response, performance tuning, and security hardening, Rapid Development Environment (RDE) deployment, log inspection, snapshots, and troubleshooting via `aio aem rde`, Jackrabbit Oak query/index tuning (property, Lucene index definitions), and extracting/inventorying JCR queries (XPath, SQL2, QueryBuilder) across a codebase.
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Read this fully before editing. Control plane: SKILL.md.
Per invocation, a deduplicated list of findings — each a client-construction site the analyzer flagged:
{
"findings": [
{
"pattern": "outbound-call-timeouts",
"file": "core/src/main/java/com/example/core/http/BadHttpService.java",
"line": 9,
"snippet": "HttpClients.createDefault()"
}
]
}Sources:
SKILL.md.The per-library recipe and skip policy apply identically in both sources. The line + snippet
locate the construction; remediation edits the surrounding builder/configuration, which may span more
lines than the snippet.
This is a mechanical fix: apply these fixed defaults directly — no value judgment, no developer
input up front. The developer tightens them in diff review if a specific upstream's SLA is stricter
(smaller is safer). Source: the CSO outage dataset (no_timeouts_in_outbound) and Adobe's
HTTP-timeout code-quality rule.
| Timeout | Meaning | Default to apply |
|---|---|---|
| connect | TCP/TLS connection establishment | 3 s |
| read / socket | wait between bytes once connected | 8 s |
| connection-request (Apache only) | wait to lease a connection from the pool | 2 s |
Never apply 0 — in Apache 4.x 0 means infinite, which is the bug.
Pick the template deterministically from the construction site's imports — no guessing:
| Import package on the construction site | Template |
|---|---|
org.apache.http.* | Apache HttpClient 4.x |
org.apache.hc.* | Apache HttpClient 5.x |
okhttp3.* | OkHttp |
java.net.http.* | JDK HttpClient |
Reuse any RequestConfig/builder already present in the file rather than introducing a second one.
org.apache.http)Set timeouts on a RequestConfig and attach it as the client's default:
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(3000) // ms — TCP connect
.setSocketTimeout(8000) // ms — read
.setConnectionRequestTimeout(2000) // ms — pool checkout
.build();
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config)
.build();HttpClients.createDefault() has no hook for config — replace it with the HttpClientBuilder.create()…build()
form above. Imports to add: org.apache.http.client.config.RequestConfig,
org.apache.http.impl.client.HttpClientBuilder (drop HttpClients import if now unused).
org.apache.hc)5.x deprecates setSocketTimeout/setConnectTimeout(int) in favour of Timeout and renames the
read knob to setResponseTimeout:
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(3))
.setResponseTimeout(Timeout.ofSeconds(8))
.setConnectionRequestTimeout(Timeout.ofSeconds(2))
.build();
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config)
.build();Import org.apache.hc.client5.http.config.RequestConfig and org.apache.hc.core5.util.Timeout.
Set the timeouts on the builder (Duration overloads, OkHttp 3.12+):
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(3))
.readTimeout(Duration.ofSeconds(8))
.writeTimeout(Duration.ofSeconds(8))
.callTimeout(Duration.ofSeconds(15)) // optional overall ceiling
.build();If the code uses new OkHttpClient() (no builder), switch to new OkHttpClient.Builder()…build().
Import java.time.Duration.
java.net.http.HttpClientThe JDK splits the timeout: the connect timeout is on the client, the read timeout is
per-request (HttpRequest.timeout). The analyzer emits a finding for each site, so the two are
fixed independently — match the template to the finding's snippet:
Client (snippet names HttpClient) — add connectTimeout; HttpClient.newHttpClient() takes
no config, so switch to the builder:
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(3))
.build();Request (snippet names HttpRequest.newBuilder) — insert .timeout(...) into the chain,
right after newBuilder(...):
HttpRequest request = HttpRequest.newBuilder(uri)
.timeout(Duration.ofSeconds(8)) // read timeout — per request
.GET()
.build();Import java.time.Duration.
Skip a finding (record it as skipped with the reason, never silently drop) when:
RequestConfig / configured builder from an
injected field, constructor parameter, or a shared factory (e.g. an AEM HttpClientBuilderFactory
or a project HttpClientFactory). Reason: timeout-configured-externally: <file>:<line> client built from shared/injected config.src/test/. Reason: test-scope: <file>:<line> outbound client in test code.framework-managed: <file>:<line>.ambiguous-construction: <file>:<line>.For partial cases — a per-request timeout exists but the client has no connect timeout (or vice versa) — do not skip: add the missing half per the per-library template.
For each finding (grouped by file):
line (the snippet is the outermost chain link).createDefault() / newHttpClient() / new OkHttpClient())
to the builder form when needed. Preserve surrounding formatting and comments.After all files are processed, continue the Verify & summarize step in ../references/runbook.md.
Before (core/src/main/java/com/example/core/http/BadHttpService.java):
package com.example.core.http;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class BadHttpService {
public String fetch() throws Exception {
CloseableHttpClient client = HttpClients.createDefault();
return client.execute(null, response -> "ok");
}
}After:
package com.example.core.http;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
public class BadHttpService {
public String fetch() throws Exception {
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(3000)
.setSocketTimeout(8000)
.setConnectionRequestTimeout(2000)
.build();
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config)
.build();
return client.execute(null, response -> "ok");
}
}What changed:
HttpClients.createDefault() → HttpClientBuilder.create().setDefaultRequestConfig(config).build() (the factory call had no config hook).RequestConfig with connect/socket/connection-request timeouts added in the same method.HttpClients import replaced by HttpClientBuilder + RequestConfig.Surgical text-level edit, not a reformatter — preserve the developer's formatting, comments, and import order. Concretely:
RequestConfig/Duration-based block) immediately before the
construction, at the construction's indentation.import …; as its own line and remove an unused
factory import by its exact full line. Do not anchor on a multi-line import block: files
interleave unrelated imports (e.g. Logger), so a block anchor is not unique and the edit fails.
Placement follows the file's existing ordering convention best-effort, but correctness never depends
on imports being grouped or contiguous.If the construction does not cleanly match one of the per-library templates (custom wrapper,
unexpected builder shape), trigger the ambiguous-construction skip rather than guessing.
Beyond mvn compile, a fixed client fails fast instead of hanging: in logs, a slow upstream now
surfaces as a prompt SocketTimeoutException / Read timed out (or HttpConnectTimeoutException for
the JDK client) rather than threads stuck in SocketInputStream.read and a climbing Jetty
request-thread count.
.tessl-plugin
skills
aem-rde
aem-workflow
code-assessment
content-distribution
create-component
assets
references
dispatcher
incident-response
references
dispatcher-foundation
performance-tuning
references
dispatcher-foundation
security-hardening
references
dispatcher-foundation
technical-advisory
references
dispatcher-foundation
workflow-orchestrator
references
dispatcher-foundation
ensure-agents-md
references
migration
references
dispatcher
legacy-ui
template-modernization
validation
scripts
dispatcher-tool
validate-migration