Events & listeners
Purpose: React to repository and platform changes with the right listener type and without melting the instance.
Who this page is for
| Audience | Why it matters to you |
|---|---|
| Backend engineers | Change-driven behaviour |
Options ranked
| Mechanism | Scope | Prefer when |
|---|---|---|
| ResourceChangeListener | Path+type filtered resource changes | Default choice for content-change reactions |
| Sling Jobs (from a listener) | Durable follow-up work | The reaction must not be lost |
| Workflow launcher | Content ops visible to admins | Business users should see/manage the automation |
| JCR ObservationListener | Low-level node events | Rarely — legacy/edge cases |
| EventHandler (OSGi events) | Platform topics (replication, page events) | Reacting to activation etc. |
ResourceChangeListener example
@Component(service = ResourceChangeListener.class, property = {
ResourceChangeListener.PATHS + "=/content/phi/plans",
ResourceChangeListener.CHANGES + "=ADDED",
ResourceChangeListener.CHANGES + "=CHANGED"
})
public class PlanChangeListener implements ResourceChangeListener {
@Reference private JobManager jobManager;
@Override public void onChange(List<ResourceChange> changes) {
changes.forEach(c -> jobManager.addJob("phi/plans/index", Map.of("path", c.getPath())));
}
}
Pattern: listen thin, work in jobs. The listener thread must return fast; heavy work goes to the job queue.
Rules
- Filter as narrowly as possible (paths, change types) — broad listeners on /content are a performance smell.
- Never write to the repository synchronously inside a listener reacting to writes — loops and contention; enqueue instead.
- Replication events differ author vs publish; decide which tier should react and guard with run-mode-scoped config.
- Expect bursts (tree activations, migrations); your handler must batch or degrade gracefully.