Expand my Community achievements bar.

Introducing Adobe LLM Optimizer: Own your brand’s presence in AI-Powered search and discovery

AEM 6.5 EventHandler Not Triggering on Page Deletion

Avatar

Level 2

Hi Everyone,

I am currently working on Adobe Experience Manager 6.5.17 and implementing a custom EventHandler to listen for page deletion events using the PageEvent.EVENT_TOPIC.

Here’s a snippet of my code:

@component(
service = EventHandler.class,
immediate = true,
property = {
EventConstants.EVENT_TOPIC + "=" + PageEvent.EVENT_TOPIC
}
)
public class PageDeletionEventHandler implements EventHandler {

private static final Logger LOG = LoggerFactory.getLogger(PageDeletionEventHandler.class);

@Override
public void handleEvent(Event event) {
LOG.info("Received event: {}", event.getTopic());
PageEvent pageEvent = PageEvent.fromEvent(event);
for (PageModification mod : pageEvent.getModifications()) {
if (mod.getType() == PageModification.ModificationType.DELETED) {
LOG.info("Page deleted at path: {}", mod.getPath());
}
}
}
}

 

The handleEvent method is triggered correctly for CREATED and MODIFIED events - but not for DELETED events when I delete pages via the AEM Sites console.

The bundle is active, the component is registered, and logging works for other event types.

Has anyone faced this issue?

2 Replies

Avatar

Community Advisor

Hi @NavyaVo,

Some page deletion actions in the Sites console are processed through JCR-level operations or as part of workflows, which sometimes prevents the PageEvent system from reliably catching the DELETED event.

Can you can try using a javax.jcr.observation.EventListener to listen for NODE_REMOVED:

@Activate
protected void activate() throws RepositoryException {
    Session session = repository.loginService("datawrite", null);
    ObservationManager observationManager = session.getWorkspace().getObservationManager();
    observationManager.addEventListener(
        this,
        Event.NODE_REMOVED,
        "/content",
        true,
        null,
        null,
        false
    );
}

This allows more fine-grained listening at the JCR level, especially for deletion operations.

Or


If you’re looking for publish-side deletion (deactivation) tracking, try ReplicationAction.EVENT_TOPIC instead:

@Component(
    service = EventHandler.class,
    immediate = true,
    property = {
        EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC
    }
)
public class PageReplicationEventHandler implements EventHandler {

    private static final Logger LOG = LoggerFactory.getLogger(PageReplicationEventHandler.class);

    @Override
    public void handleEvent(Event event) {
        ReplicationAction action = ReplicationAction.fromEvent(event);
        if (ReplicationActionType.DEACTIVATE.equals(action.getType())) {
            LOG.info("Page deactivated: {}", action.getPath());
        }
    }
}

 Reference: https://experienceleague.adobe.com/en/docs/experience-manager-learn/cloud-service/aem-eventing/overv...

Hope this helps!


Santosh Sai

AEM BlogsLinkedIn


Avatar

Community Advisor

Hi @NavyaVo ,

Try below solution:

To reliably detect page deletions, listen for JCR NODE_REMOVED events under /content.

JCR EventListener Implementation

@Component(immediate = true, service = EventListener.class)
public class PageDeletionJcrEventListener implements EventListener {

    private static final Logger LOG = LoggerFactory.getLogger(PageDeletionJcrEventListener.class);

    @Reference
    private SlingRepository repository;

    private Session session;

    @Activate
    protected void activate() throws Exception {
        session = repository.loginService("datawrite", null);
        Workspace workspace = session.getWorkspace();
        ObservationManager observationManager = workspace.getObservationManager();

        observationManager.addEventListener(
            this,
            Event.NODE_REMOVED,
            "/content",
            true,
            null,
            null,
            false
        );
        LOG.info("JCR EventListener registered for NODE_REMOVED under /content");
    }

    @Deactivate
    protected void deactivate() {
        if (session != null && session.isLive()) {
            session.logout();
        }
    }

    @Override
    public void onEvent(EventIterator events) {
        while (events.hasNext()) {
            Event event = events.nextEvent();
            try {
                String path = event.getPath();
                LOG.info("Node removed at path: {}", path);
            } catch (RepositoryException e) {
                LOG.error("Error handling node removed event", e);
            }
        }
    }
}

Service User Mapping (Mandatory for loginService)

Make sure you have a system user (datawrite) with read access under /content and register a mapping in org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended:

your.bundle.symbolic.name:datawrite=datawrite-service-user

And ensure this user has read access to /content, or use jcr:read permission via an ACL.

 

Also Track Deactivation (Replication)

To track page deactivations, use:

@component(
    service = EventHandler.class,
    immediate = true,
    property = {
        EventConstants.EVENT_TOPIC + "=" + ReplicationAction.EVENT_TOPIC
    }
)
public class PageReplicationEventHandler implements EventHandler {

    private static final Logger LOG = LoggerFactory.getLogger(PageReplicationEventHandler.class);

    @Override
    public void handleEvent(Event event) {
        ReplicationAction action = ReplicationAction.fromEvent(event);
        if (ReplicationActionType.DEACTIVATE.equals(action.getType())) {
            LOG.info("Page deactivated: {}", action.getPath());
        }
    }
}