Respond to a Page Create, Copy, Move, Delete, or Update Event
Introduction
Goal
Extend the page create, copy, move, delete, or update process with additional custom behavior.
Summary
CMS users can perform a number of page actions within the Experience manager, specifically they can create, copy, move, delete, and update pages via the Page Settings. Before processing such an action, the delivery tier sends an event to its internal event bus, enabling developers to extend the process with additional behavior.
Extend the Page Actions
When the delivery tier (HST) processes a page action, and before persisting any changes to the repository, a PageEvent is sent to the synchronous HST internal event bus, of a type corresponding to the action that took place. Developers can create a listener for this PageEvent and add custom behavior to the page action (like invoking some workflow on some content, sending an event to a message bus, removing an experiment that was running on the source page, etc). Information about the page action is exposed via the event context, accessible via the PageEvent’s getPageActionContext method. Through a PageEvent, a developer can also abort the entire page action.
Because the code in the HST that posts the event also handles the persistence of the session changes at the end, a developer should never save the JCR session that can be accessed via either
pageEvent.getPageActionContext().getRequestContext().getSession();
or via any method of the PageActionContext that exposes a JCR Node, for example in the PageCopyEvent
copyEvent.getPageActionContext().getNewSiteMapItemNode().getSession()
Create a Custom Listener for a PageEvent
The example below is for a PageCopyEvent listener. To create listeners for other action types, use the appropriate PageEvent class (PageCreateEvent, PageCopyEvent, PageMoveEvent, PageDeleteEvent, or PageUpdateEvent). Different information is exposed per event type, via different PageActionContext implementations. Please consult the JavaDocs API Documentation for classes PageCreateContext, PageCopyContext, PageMoveContext, PageDeleteContext, and PageUpdateContext.
package com.example.pagecopy; import org.hippoecm.hst.pagecomposer.jaxrs.api.ChannelEventListenerRegistry; import org.hippoecm.hst.pagecomposer.jaxrs.api.PageCopyEvent; import org.onehippo.cms7.services.eventbus.Subscribe; public class PageCopyEventListener { @SuppressWarnings("UnusedDeclaration") public void init() { ChannelEventListenerRegistry.get().register(this); } @SuppressWarnings("UnusedDeclaration") public void destroy() { ChannelEventListenerRegistry.get().unregister(this); } @Subscribe public void onPageEvent(PageCopyEvent event) { if (event.getException() != null) { return; } // DO YOUR STUFF BUT MAKE SURE TO NEVER // SAVE THE JCR SESSION FOR THAT IS ACCESSIBLE VIA // THE PageCopyEvent#getPageActionContext#getRequestContext } }
The last step is to make sure your PageCopyEventListener is initialized as a Spring bean. For example, add a Spring XML configuration bean in site/components/src/main/resources/META-INF/hst-assembly/overrides/page-event-listeners.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.example.pagecopy.PageCopyEventListener" init-method="init" destroy-method="destroy"/> </beans>
Now, whenever a user copies a page via the Page Settings, the above PageCopyEventListener#onPageEvent is invoked before any changes are persisted into the repository.
Abort Page Action with the PageEvent
A listener for page events can abort a page action by setting an exception on the event object. This can be useful in case some requirement is not met or the post-processing fails. See Abort an Experience Manager Action for details.