| name | remove-deprecated-api |
| description | AEM Cloud Service expert skill — migrate deprecated and removed Java APIs to
comply with AEM as a Cloud Service enforcement policies. Detection is **plugin-driven,
not table-driven**: the skill runs the AEM Analyser Maven Plugin
(`com.adobe.aem:aemanalyser-maven-plugin`) at its latest published version against the
project and parses the `region-deprecated-api` output — the same data Cloud Manager's
pipeline uses. Each finding carries the plugin's own deprecation hint (typically a
successor package parsed from the analyser message), which drives the fix. Use when
auditing deprecated APIs, fixing Cloud Manager pipeline failures citing
`region-deprecated-api` / `api-regions-check` / `Import-Package not satisfied`, or
proactively modernizing AEM projects before enforcement deadlines.
|
| license | Apache-2.0 |
Remove Deprecated API — AEM as a Cloud Service
This pattern is executed by the code-assessment runbook — follow
../references/runbook.md for the outer flow (preflight →
plan → apply → verify, run log). This skill supplies the plugin-driven detection and
the hint-driven fix recipe the runbook applies.
Overview
Adobe curates the list of deprecated / removed AEM APIs inside the AEM SDK's
api-regions metadata; Cloud Manager's region-deprecated-api analyser task consumes
that JSON at build time. The AEM Analyser Maven Plugin
(com.adobe.aem:aemanalyser-maven-plugin) runs the same task locally against the
project's built bundles. This skill uses the plugin as its detection engine — no
curated tables, no static lists, no drift.
For each deprecated package the plugin reports, its log line contains a hint: the
deprecated.msg field from the SDK metadata, which typically names a successor
package (e.g. "Please use org.apache.sling.xss instead"). Fixes are derived from
that hint at plan time. When the hint names no successor, the recipe consults the
Adobe Experience League API-removal guidance as a documented fallback.
Classification — confirm this pattern applies
- Any
*.java, pom.xml, or OSGi config file the AEM Analyser Maven Plugin reports
under region-deprecated-api (i.e. any Usage of deprecated ... found log line
produced by mvn verify against the project).
- Cloud Manager code-quality pipeline failures citing
region-deprecated-api,
api-regions-check, Import-Package not satisfied, or bundle-unversioned-packages
violations.
The plugin only reports past-due deprecations by default (entries whose
for-removal date has already elapsed). Future-dated deprecations are not touched;
re-running the skill after each removal date passes picks them up automatically — the
list is live.
Discovery — two-phase
The detector lives in the shared Java analyzer (scripts/analyzer/detectors/RemoveDeprecatedApi.java),
same shape as every other pattern's detector — but its rules are loaded at run time
from a preflight-produced cache, not hardcoded.
Phase 1 — preflight (populates the rules cache)
bash plugins/aem/cloud-service/skills/code-assessment/remove-deprecated-api/scripts/detect.sh <project-root>
detect.sh:
- Resolves the latest
com.adobe.aem:aemanalyser-maven-plugin and the latest
com.adobe.aem:aem-sdk-api releases from Maven Central (maven-metadata.xml); each
can be pinned with --pin-plugin <version> / --pin-sdk <version>. The freshest
SDK is used by default because Cloud Manager itself runs the analyser against the
latest SDK — matching that behaviour surfaces every deprecation the pipeline will
flag. If the project's pom.xml pins an older SDK via <sdkVersion>X.Y.Z</sdkVersion>
or <useDependencyVersions>true</useDependencyVersions> inside the analyser plugin
config, detect.sh overrides at the CLI (-DsdkVersion=<latest> and
-DsdkUseDependency=false) so the fresh set is used just for the preflight — no
pom edit. Pass --respect-pom-sdk to honour the pom's pin instead.
- Invokes the analyser by its fully-qualified
com.adobe.aem:aemanalyser-maven-plugin:<version>:project-analyse coordinates, so the
resolved version runs whether or not the project declares the plugin — the pom is
never modified (no patch, no backup, no restore). Command shape:
mvn package com.adobe.aem:aemanalyser-maven-plugin:<version>:project-analyse … — the
package phase (override with --goal) builds the module artifacts that
project-analyse inspects. Log path: /tmp/aem-analyser.log (override with --log <path>).
- Parses
Usage of deprecated package found : <pkg> : <hint> Deprecated since <since> For removal : <date>
and Usage of deprecated library found : <lib>, package(s) : <start>...<end> : <hint> lines.
- Writes the rules cache TSV —
<package>\t<hint>\t<for_removal> per line — at
$AEM_DEPRECATED_API_RULES (env override) or
$TMPDIR/aem-code-assessment/deprecated-api-rules.tsv (default).
- Emits a JSON summary on stdout (findings + meta) for callers that don't chain
through
analyze.sh.
Phase 2 — analyzer (consumes the cache, emits findings)
bash plugins/aem/cloud-service/skills/code-assessment/scripts/analyze.sh <workspace-root>
The Java RemoveDeprecatedApi detector reads the rules TSV, matches each rule's
package against every import in the corpus (longest-prefix match), applies today's
past-due gating as a defence-in-depth, and emits findings in the standard
{pattern,file,line,snippet} shape with an added hint field carrying the analyser
message.
Findings shape — the standard runbook shape plus an optional hint:
{
"findings": [
{
"pattern": "remove-deprecated-api",
"file": "core/src/main/java/com/example/MyService.java",
"line": 5,
"snippet": "org.apache.log4j.Logger",
"hint": "The log4j 1.x libraries are deprecated. Please use org.slf4j instead."
}
],
"warnings": []
}
If the cache is missing — detect.sh was not run, or was run offline and failed —
the detector emits a single warning:
deprecated-api-rules-missing: expected TSV at <path> — run remove-deprecated-api/scripts/detect.sh preflight first
and produces no findings for this pattern. Other detectors continue unaffected.
Scope: workspace roots only. Exclude code-assessment/ skill files.
Resolution contract
hint-driven — every fix derives from the analyser's hint field for that finding.
The recipe (recipe.md Step 3) parses the hint for a successor-package phrase
("Please use X instead", "Use X instead", "X should be used") and applies the
edit. When the hint names no successor, the recipe falls back to Adobe Experience
League's API-removal guidance page via WebFetch.
Verification — before applying, the successor must be resolvable on the project's
classpath. If it is not, either add the required Maven dependency (with user consent)
or record the finding as manual-action-required.
Manual-only items (cannot be auto-fixed; document in report, do not attempt edits):
- Deep integration cases where hint says "not supported in AEM as a Cloud Service"
with no successor named on Experience League (e.g.
org.apache.felix.webconsole,
parts of com.drew).
- Guava usage beyond simple
Lists.newArrayList() / ImmutableList.of() — caching,
event bus, complex data structures — where replacement requires design decisions.
- Reflection or dynamic loading against the deprecated type — the scanner cannot see
it and the fix is not mechanical.
Review checklist
Troubleshooting fingerprints
| Symptom | Likely cause | Action |
|---|
detect.sh fails at plugin resolution step | Plugin not in local Maven cache | Pass --pin-plugin <version> with a locally available version |
| The build fails before the analyser goal runs | Baseline compile failure in the package phase | Fix the baseline build first (per runbook), then re-run detection |
| Hint is empty for a finding | SDK deprecation message is descriptive only, or the finding came from library grouping without a msg | Consult Experience League for the successor; if still absent, record as manual-only |
Import-Package not satisfied on rerun | Successor package not on the module's classpath | Add the required Maven dependency (with user consent) or pick a JDK stdlib alternative |
Analyser reports a package with no import match in-workspace | Deprecated API pulled in transitively by a third-party bundle | Cannot fix in customer code; report as third-party dependency upgrade needed |
Recipe pointer
Read recipe.md fully before applying. The recipe covers the plugin
setup + preflight scan, the hint parsing rules, the Experience League fallback flow,
the AI-fix loop for compilation errors introduced by rewrites, and the report format.