Enonic Event Manager
Procedures
Step 1: Detect the Enonic XP project
- Execute
node scripts/find-enonic-targets.mjs .to locate Enonic XP project roots in the workspace. - If the script returns an empty array, stop and explain that no Enonic XP project was found.
- If multiple projects are found, ask which project should receive the integration.
- Identify the application key from
gradle.properties(appName) orbuild.gradle.
Step 2: Determine integration direction
- Classify the task as one of: outbound event listener (XP reacts to internal events and calls an external system), outbound webhook config (XP sends webhook payloads via built-in config), inbound webhook endpoint (XP receives payloads from an external system), or mixed (combination).
- Read
references/event-reference.mdto identify the correct event types, listener patterns, and filtering strategies. - Read
references/webhook-reference.mdwhen the task involves outbound webhook configuration or inbound HTTP service endpoints.
Step 3: Implement outbound event listener (if applicable)
- Read
assets/event-listener.template.tsas a starting scaffold. - Register the event listener in the application's
main.ts(ormain.js) controller using lib-event'slistener()function. - Use the
typeparameter with a pattern matching the target node events (e.g.,node.pushed,node.created,node.updated,node.deleted). - Filter events by path within the callback by checking
event.data.nodes[].pathto restrict processing to the intended content tree. - When the listener must call an external HTTP endpoint, use lib-httpClient's
request()function inside the callback or delegate to a background task. - For long-running processing, delegate work from the event callback to a background task using lib-task's
executeFunction()to avoid blocking the event thread. - Read
references/examples.mdfor complete integration patterns including CDN invalidation, search reindexing, and notification dispatch.
Step 4: Configure outbound webhooks (if applicable)
- Read
references/webhook-reference.mdfor thecom.enonic.xp.webhooks.cfgconfiguration format. - Create or update the file at
XP_HOME/config/com.enonic.xp.webhooks.cfgwith webhook entries specifying the target URL and event types. - Validate that the configured event types match the intended content lifecycle events.
- Use HTTPS URLs for webhook targets.
- Never write actual secret values into configuration files or source code. Use descriptive placeholder tokens (e.g.,
REPLACE_WITH_CDN_SECRET) and instruct the operator to substitute real credentials out-of-band. Secrets must be managed by the operator through secure deployment pipelines, environment variables, or secret management tools—not committed to files.
Step 5: Implement inbound webhook endpoint (if applicable)
- Read
assets/http-service.template.tsas a starting scaffold. - Create an HTTP service controller at
src/main/resources/services/<serviceName>/<serviceName>.ts. - Export a
post(req)function that parses the incoming JSON payload fromreq.body. - Reject payloads exceeding a reasonable size limit (e.g., 1 MB) before parsing.
- Validate the inbound payload by checking required fields, authentication headers, or HMAC signatures before processing.
- Sanitize all string fields from the external payload before using them in content operations: trim whitespace, enforce maximum lengths, strip or escape HTML/script content, and reject values containing path traversal sequences (
..,/,\). - Use an allowlist of expected field names rather than passing the raw payload object to content APIs.
- Return appropriate HTTP status codes:
200for success,400for malformed payloads,401for authentication failures,413for oversized payloads,500for unexpected errors. - When inbound payloads trigger content creation or modification, use lib-content or lib-node APIs within a context run to ensure proper permissions. Never pass unsanitized external values as content names, paths, or keys.
Step 6: Wire async processing with lib-task (if applicable)
- When event handling or webhook processing requires heavy or time-consuming work, wrap it in
executeFunction()from lib-task. - Report progress from long-running tasks using
progress()to allow monitoring. - Read
references/event-reference.mdfor the task event lifecycle (task.submitted,task.updated,task.finished,task.failed).
Step 7: Validate the integration
- Execute
node scripts/find-enonic-targets.mjs .to confirm the project still resolves correctly. - Verify that the event listener registration is in the application's
main.tsormain.jsfile, which runs at application startup. - Confirm that outbound HTTP calls use HTTPS and include error handling for network failures and non-2xx responses.
- Confirm that no actual secret values, API keys, or credentials appear in generated source code or configuration files—only placeholder tokens.
- Confirm that inbound webhook endpoints sanitize and allowlist all fields from external payloads before passing them to content APIs.
- If a webhook config file was created, confirm the event type patterns match the intended triggers.
- Run the workspace build to verify no compilation errors.
- Read
references/troubleshooting.mdwhen events do not fire, webhook deliveries fail, or inbound requests are rejected.
Error Handling
- If
node scripts/find-enonic-targets.mjs .finds no projects, confirm thatbuild.gradlereferencescom.enonic.xpplugins or that asrc/main/resources/site/directory exists. - If events do not fire after registering a listener, read
references/troubleshooting.mdto check listener registration location, event type patterns, and cluster vs. local event scope. - If outbound HTTP calls fail, verify the target URL, network access from the XP instance, and that the operator has substituted placeholder tokens with real credentials.
- If inbound webhook requests return 404, confirm the service controller path follows
services/<name>/<name>.tsand the application is deployed. - If background tasks fail silently, check task state using
taskLib.list()and inspect logs for errors within the task function.