aa-conversion-funnel-a…
Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have…
AEM Cloud Service expert skill for OSGi Event Admin handlers (non-resource events). Covers migration of javax.jcr.observation.EventListener (residual non-resource cases) and OSGi EventHandler with inline business logic to the lightweight EventHandler + JobConsumer split.
$ npx -y skills add adobe/skills --skill event-migration --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/event-migrationContext preview
The summary Claude sees to decide when to auto-load this skill.
AEM Cloud Service expert skill for OSGi Event Admin handlers (non-resource events). Covers migration of javax.jcr.observation.EventListener (residual non-resource cases) and OSGi EventHandler with inline business logic to the lightweight EventHandler + JobConsumer split.
name: event-migration description: AEM Cloud Service expert skill for OSGi Event Admin handlers (non-resource events). Covers migration of javax.jcr.observation.EventListener (residual non-resource cases) and OSGi EventHandler with inline business logic to the lightweight EventHandler + JobConsumer split. Includes routing rules (resource events go to resource-change-listener, external notification goes to AEM Eventing), TopologyEventListener for leader-only execution, replication and workflow event patterns, service-user setup, review checklist, troubleshooting, and common pitfalls. license: Apache-2.0
`org.osgi.service.event.EventHandler` is the API for reacting to **non-resource** OSGi Event Admin events on AEM CS — replication events (`com.day.cq.replication.ReplicationEvent.EVENT_TOPIC`), workflow events (`com/adobe/granite/workflow/*`), and custom inter-bundle event topics. The handler runs on a shared OSGi event thread and **must** stay lightweight — all business logic must be offloaded to a Sling Job via `JobManager.addJob()`.
**Three CS-specific constraints every event handler must satisfy:**
| Constraint | Why | |-----------|-----| | No `ResourceResolver` / `Session` / JCR ops inside `handleEvent()` | Blocks the shared OSGi event-admin thread; can delay every other registered handler | | `getServiceResourceResolver(SUBSERVICE)` in the consumer | `getAdministrativeResourceResolver` is removed from the CS SDK | | Leader-only handlers must implement `TopologyEventListener` and check `isLeader` | A simple run-mode check fires on every author cluster pod — `TopologyEventListener` is the supported way to elect a single leader |
> **`handleEvent()` runs synchronously on a shared OSGi thread.** Doing repository, network, or workflow work inline blocks event delivery for every other handler subscribed to anything. Always offload to a `JobConsumer`.
---
**Use this skill when** the source listens to a **non-resource** OSGi Event Admin topic:
| Source topic | Description | |--------------|-------------| | `com.day.cq.replication.ReplicationEvent.EVENT_TOPIC` | Replication actions (activate, deactivate, etc.) | | `com/adobe/granite/workflow/*` | Workflow lifecycle events | | Custom OSGi topics posted by another bundle | Inter-bundle event signaling | | Other non-resource OSGi events | Any OSGi event that is not a resource-change topic |
**Route elsewhere when:**
| Source observes… | Use instead | |------------------|-------------| | Repository content (page, asset, property added/changed/removed) | **`resource-change-listener` skill** — `ResourceChangeListener` is the supported API on CS | | External system notification (Adobe I/O Events, App Builder, webhooks, downstream services) | **AEM Eventing** — cloud-native, runs outside AEM, distinct from OSGi Event Admin | | Anything subscribed to `org/apache/sling/api/resource/Resource/*` | **`resource-change-listener` skill** — those OSGi resource topics are a deprecated internal Sling dispatcher detail |
**Do not** subscribe a new `EventHandler` to `org/apache/sling/api/resource/Resource/ADDED|CHANGED|REMOVED`. Those topics are an internal Sling dispatcher detail, deprecated as an application-facing API. Use `ResourceChangeListener` for resource observation.
Always subscribe via a documented topic constant — never invent or copy-paste a topic string. The canonical constants live in the producing bundle's API:
| Producing API | Constant | |---------------|----------| | Replication | `com.day.cq.replication.ReplicationEvent.EVENT_TOPIC` | | Workflow | `com.adobe.granite.workflow.event.WorkflowEvent.EVENT_TOPIC` — combine with `WorkflowEvent.EVENT_TYPE` property to discriminate the sub-event | | Sling Jobs (lifecycle) | `org.apache.sling.event.jobs.NotificationConstants.*` | | Custom bundle topics | Check the producing bundle's source or documentation for its declared `static final String` topic constant |
A typo'd topic string compiles fine and silently subscribes to a topic that nothing posts to — the handler is `ACTIVE` but never fires. Reference the constant in code instead of duplicating the literal string.
---
**Implements `EventHandler` for a non-resource topic** and `handleEvent()` only enqueues jobs → Already compliant — verify against the [Review Checklist](#review-checklist) only.
**Implements `EventHandler` for a non-resource topic** and `handleEvent()` contains business logic (resolver, JCR ops, heavy processing) → Apply **E1–E5**.
**Implements `javax.jcr.observation.EventListener`** for a concern that **cannot** be expressed as a `ResourceChangeListener` (rare — most legacy JCR listeners should route to the `resource-change-listener` skill) → Apply **E0** (convert to `EventHandler` for the appropriate non-resource topic) then **E1–E5**. If unsure whether RCL covers it, prefer RCL and ask before falling through to this skill.
**One pattern per session.** If the bundle has multiple legacy handlers, migrate one class at a time.
**Before starting:** Read [`../references/aem-cloud-service-pattern-prerequisites.md`](../references/aem-cloud-service-pattern-prerequisites.md) and apply SCR→DS, service-user, and SLF4J fixes if present in the same changeset.
---
Detection is performed by the analyzer ([`../scripts/analyze.sh`](../scripts/README.md)), run by the runbook:
bash ../scripts/analyze.sh <workspace-root> --pattern event-migration
**Match criteria (what the detector flags):** a class that **`implements org.osgi.service.event.EventHandler`** or **`javax.jcr.observation.EventListener`** (import-aware) — both map here per the BPA subtype taxonomy.
Emitted at the class declaration, with the class header as the snippet. Parse-level only — direct `implements` clause; the subscribed topic (resource vs non-
Repo: adobe/skills
Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have…
Generates a concise, executive-ready performance summary covering key metrics, trends, and…
Produces a compact KPI digest showing how key metrics changed over a period and what's…
Compares the performance of two or more audience segments across key metrics side by side.…
Identifies which items (pages, campaigns, products, channels, regions) had the biggest…
Comprehensive dimension analysis and reporting for CJA. Use this skill whenever the user…