plugins/aem/cloud-service/skills/best-practices/SKILL.md
AEM as a Cloud Service Java/OSGi best practices, guardrails, and legacy-to-cloud pattern transformations. Use for Cloud Service–correct bundles, deprecated APIs, schedulers, ResourceChangeListener, replication, Replicator, JCR observation (javax.jcr.observation.EventListener), OSGi Event Admin (org.osgi.service.event.EventHandler), DAM AssetManager, BPA-style fixes, HTL (Sightly) Cloud SDK lint warnings (data-sly-test redundant constant value comparison), or any time you need the detailed pattern reference modules under this skill.
npx skillsauth add adobe/skills best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Platform guidance for AEM as a Cloud Service: Java/OSGi (what to use, what to avoid, how to refactor legacy patterns) and HTL (component .html templates, Cloud SDK HTL lint).
This skill holds the pattern transformation modules (references/*.md). They ship with the aem-cloud-service plugin; use this skill without the migration skill for greenfield or maintenance work that only needs these references. Use migration when you need BPA/CAM orchestration on top.
Quick pick: Open the Pattern Reference Modules table below → jump to the matching references/<file>.md → read it fully before editing. For Java: Felix SCR, resolvers, or logging, use Java / OSGi baseline links first when those appear in the same change set.
Use this skill when you need to:
eventListener), OSGi event handlers (eventHandler), and DAM assetsdata-sly-test: redundant constant value comparisonFor BPA/CAM orchestration (collections, CSV, MCP project selection), use the migration skill (skills/aem/cloud-service/skills/migration/).
Each supported pattern has a dedicated module under references/ relative to this SKILL.md.
| Pattern / topic | BPA Pattern ID | Module file | Status |
|-----------------|----------------|-------------|--------|
| Scheduler | scheduler | references/scheduler.md | Ready |
| Resource Change Listener | resourceChangeListener | references/resource-change-listener.md | Ready |
| Replication | replication | references/replication.md | Ready |
| Event listener (JCR observation) | eventListener | references/event-migration.md | Ready |
| Event handler (OSGi Event Admin) | eventHandler | references/event-migration.md | Ready |
| Asset Manager | assetApi | references/asset-manager.md | Ready |
| Felix SCR → OSGi DS | — | references/scr-to-osgi-ds.md | Ready |
| ResourceResolver + SLF4J | — | references/resource-resolver-logging.md | Ready |
| HTL: data-sly-test redundant constant | — (HTL lint) | references/data-sly-test-redundant-constant.md | Ready |
| (Prerequisites hub) | — | references/aem-cloud-service-pattern-prerequisites.md | — |
Event listener vs event handler (not the same): eventListener is JCR observation — the JCR API for repository change callbacks (javax.jcr.observation.EventListener, onEvent). eventHandler is OSGi Event Admin — whiteboard-style OSGi events (org.osgi.service.event.EventHandler, handleEvent). Both migrate via references/event-migration.md (Path A vs Path B). resourceChangeListener is separate: Sling ResourceChangeListener, module references/resource-change-listener.md.
Before changing code for a pattern: read the module for that pattern in full. Modules include classification criteria, ordered transformation steps, and validation checklists.
SCR→DS and ResourceResolver/logging are reference modules under references/ — not separate skills. Read them when relevant instead of re-embedding the same steps inside each pattern file.
references/aem-cloud-service-pattern-prerequisites.mdreferences/scr-to-osgi-ds.md, references/resource-resolver-logging.mdThese rules apply to every pattern module. Violation means incorrect migration or unsafe Cloud Service code.
scr-to-osgi-ds.md and resource-resolver-logging.md when SCR, ResourceResolver, or logging are in scope (pattern modules link via the prerequisites hub; do not duplicate long guides inline)isAuthor() run mode checks)When no BPA list exists, scan imports and types to pick a module:
| Look for | Pattern |
|----------|---------|
| org.apache.sling.commons.scheduler.Scheduler or scheduler.schedule( with Runnable | scheduler |
| implements ResourceChangeListener | resourceChangeListener |
| com.day.cq.replication.Replicator or org.apache.sling.replication.* | replication |
| JCR observation: javax.jcr.observation.EventListener, onEvent(EventIterator), javax.jcr.observation.* | eventListener |
| OSGi Event Admin: org.osgi.service.event.EventHandler, substantive handleEvent (resolver/session/node work) | eventHandler |
| com.day.cq.dam.api.AssetManager create/remove asset APIs | assetApi |
| org.apache.felix.scr.annotations | read references/scr-to-osgi-ds.md (often combined with a BPA pattern) |
| getAdministrativeResourceResolver, System.out / printStackTrace | read references/resource-resolver-logging.md |
| HTL: build warning data-sly-test: redundant constant value comparison, or .html under ui.apps / jcr_root with bad data-sly-test | read references/data-sly-test-redundant-constant.md |
If multiple patterns match, ask which to fix first.
The migration skill defines one-pattern-per-session workflow, BPA/CAM/MCP flows, and user messaging. It delegates all detailed transformation steps to this skill's references/ modules. It uses a {best-practices} repo-root path alias to this folder (see its SKILL.md). Keep platform truth here; keep orchestration there.
tools
Use the run-workflow MCP to discover, compose, execute, publish, and save Adobe Firefly workflows. TRIGGER when: user asks what actions are available, what the MCP can do, how to process images/video/3D via workflow, wants to build/run/save/publish a workflow, OR pastes any workflow/batch/execution ID. BARE ID (UUID/workflowId/batchId) = INSPECT ONLY — call inspect_run, NEVER run_workflow_submit. ALWAYS call list_actions first for capability/discovery questions. DO NOT TRIGGER for direct Firefly API calls without MCP (use firefly-api-specs).
tools
Run predefined featured workflows via run-workflow MCP. TRIGGER when user names a featured workflow (retargeting, banners at scale, localization, packaging, banner advertising, etc.) or asks to run a known marketing/production workflow. Requires run-workflow MCP. ALWAYS call get_featured_workflow before compose_workflow. DO NOT TRIGGER for custom one-off workflows with no named template — use run-workflow skill.
tools
Migrate an Adobe Commerce App Builder project from the Integration Starter Kit or Checkout Starter Kit to the new App Management approach. Run from the root of the App Builder project to be migrated. Pass --auto to skip confirmation prompts (suitable for CI or batch use) — auto mode prints a summary of all Q&A questions answered with their defaults. Pass --doc-scan-only to scan README.md and env.dist for outdated content without modifying any files. Use when the user wants to migrate an App Builder project from the Integration Starter Kit or Checkout Starter Kit to the App Management approach, or mentions upgrading their Adobe Commerce extension architecture.
development
Add or modify webhook interceptors in an Adobe Commerce app. Use when the user wants to intercept Commerce operations to validate input, append data, or modify behavior — before or after execution. Requires a base app initialized with commerce-app-init.