Respond to Publish Changes, Discard Changes, and Create Preview Configuration Channel Events
Introduction
Goal
Implement custom logic which gets triggered when a user publishes or discards channel changes in the Channel Manager, or when a channel's preview configuration is created.
Background
Users can publish or discard changes they made to a channel in the Channel Manager. Also, when a channel is edited by a user for the first time, a preview configuration is created. A delivery tier implementation may require additional validation and/or processing of these actions. This is possible by subscribing to Channel Events that get published to the delivery tier's internal event bus when these user actions occur.
Channel Events
Channel Events are published to the synchronous HST internal event bus to enable custom code to hook into the process, and if needed, add some extra logic or short-circuit the process (in case something fails or some requirement is not met).
At this moment, a ChannelEvent object is published to the synchronous HST event bus on the following occasions:
- Publication of channel manager changes of user(s) (ChannelEvent.ChannelEventType#PUBLISH)
- Discarding of channel manager changes of user(s) (ChannelEvent.ChannelEventType#DISCARD)
- Creation of the preview configuration (ChannelEvent.ChannelEventType#PREVIEW_CREATION)
When the event is published, changes are not yet persisted.
Respond to a ChannelEvent
The following example shows a listener class which subscribes to Channel Events.
A listener must always check whether:
- an exception has already been added to the Channel Event (through ChannelEvent.getException())
- the Channel Event is of the expected type (through ChannelEvent.getChannelEventType())
site/src/main/java/org/example/listeners/MyChannelEventListener.java
package org.example.listeners; import org.hippoecm.hst.core.container.ComponentManager; import org.hippoecm.hst.core.container.ComponentManagerAware; import org.hippoecm.hst.pagecomposer.jaxrs.api.ChannelEvent; import org.hippoecm.hst.pagecomposer.jaxrs.api.ChannelEvent.ChannelEventType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.eventbus.Subscribe; public class MyChannelEventListener implements ComponentManagerAware { private static final Logger log = LoggerFactory.getLogger(MyChannelEventListener.class); private ComponentManager componentManager; @Override public void setComponentManager(ComponentManager componentManager) { this.componentManager = componentManager; } public void init() { componentManager.registerEventSubscriber(this); } public void destroy() { componentManager.unregisterEventSubscriber(this); } @Subscribe public void onEvent(ChannelEvent event) { if (event.getException() != null) { return; } final ChannelEventType type = event.getChannelEventType(); if (type != ChannelEventType.DISCARD && type != ChannelEventType.PUBLISH) { log.debug("Skipping ChannelEvent '{}' because type is not equal to {} or {}.", type, ChannelEventType.PUBLISH, ChannelEventType.DISCARD); return; } log.info("Channel: {}, event: {}, user: {}", event.getEditingPreviewSite().getName(), event.getChannelEventType(), event.getUserIds()); } }
The listener must be configured as a Spring bean like in the example below:
site/src/main/resources/META-INF/hst-assembly/overrides/channel-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="org.example.listeners.MyChannelEventListener" init-method="init" destroy-method="destroy"/> </beans>
Short-circuit a Channel Action
A Channel Event Listener can short-circuit the action that caused an event by setting a RuntimeException on the ChannelEvent object:
event.setException(new RuntimeException("This will shortcircuit the action"));
This is useful in case some requirement is not met or the post-processing fails. When a listener short-circuits a channel action, the action is aborted and a generic error message is displayed in the CMS UI.