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.
Handle Channel Events in a Project Context
If you use the Projects feature (available to Bloomreach Experience Manager customers), you may want to respond differently depending on the context of a channel event. For example, a channel publish event can either mean changes to a channel were published to go live, or changes to a channel were submitted in a project and won't go live until the project is merged.
You can find out if a ChannelEvent was triggered within the context of the channel core or within a channel branch as part of a project as follows:
event.getEditingPreviewSite().getChannel().getBranchOf();
If the context of the event is the channel core, getBranchOf() will return null.
If the context of the event is a channel branch as part of a project, getBranchOf() will return the ID of the branched channel.