/* * Copyright 2012 david gonzalez. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.activecq.samples.eventhandlers.impl; import org.apache.commons.lang.StringUtils; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Properties; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingConstants; import org.apache.sling.event.EventUtil; import org.apache.sling.event.jobs.JobProcessor; import org.apache.sling.event.jobs.JobUtil; import org.osgi.framework.Constants; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; import org.osgi.service.event.EventHandler; import java.util.Dictionary; import java.util.Hashtable; @Component( label = "Samples - Custom Event Publisher", description = "Sample implementation of a Custom Event Publisher based on Sling", immediate = true, metatype = false ) @Properties({ @Property( label = "Vendor", name = Constants.SERVICE_VENDOR, value = "ActiveCQ", propertyPrivate = true ), @Property( label = "Event Topics", value = { org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED, org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_CHANGED, org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_REMOVED }, description = "[Required] Sling Event Topics this event handler will to respond to.", name = "event.topics", propertyPrivate = true ) }) @Service public class SampleEventPublisher implements JobProcessor, EventHandler { public static final String JOB_TOPIC_POKED = "samples/events/poked"; @Reference private EventAdmin eventAdmin; @Override public void handleEvent(Event event) { if (EventUtil.isLocal(event)) { // If this server created the event // then only this server should process the event // This will call this's process(..) method, passing in the event obj // JobUtil.processJob(..) sends/checks for an ack for this job JobUtil.processJob(event, this); return; } } @Override public boolean process(Event event) { final String path = (String) event.getProperty(SlingConstants.PROPERTY_PATH); final String resourceType = (String) event.getProperty(SlingConstants.PROPERTY_RESOURCE_TYPE); if (!StringUtils.startsWith(path, "/content/samples")) { // Only handle events here from resources under /content/samples return true; } try { // Only return false if job processing failed and the job should be rescheduled return fowardEvent(path); } catch (Exception ex) { // If this event could not be processes to satisfaction, return false // so it can be rescheduled. return false; } } private boolean fowardEvent(final String path) throws Exception { boolean isDistributableEvent = false; boolean sendAsync = true; // It is highly recommended to stick w String and Scalar datatypes to avoid // issues marshalling data across the wire to other servers in the cluster // All value Objects must be serializable final Dictionary<String, Object> eventProperties = new Hashtable<String, Object>(); // The topic must be set in the Event's properties eventProperties.put(EventUtil.PROPERTY_JOB_TOPIC, JOB_TOPIC_POKED); // Add any other data that Event Handler will need to process this Event eventProperties.put("resourcePath", path); // Create event object; Event pokedEvent; if (isDistributableEvent) { // Send this event to other servers in the cluster; This is rarely // what you want. pokedEvent = EventUtil.createDistributableEvent(EventUtil.TOPIC_JOB, eventProperties); } else { // Send the event out to this server's event queue. // This is almost always what you want pokedEvent = new Event(EventUtil.TOPIC_JOB, eventProperties); } // Send the new event out into the world to be handled if (sendAsync) { // send ASYNCHRONOUSLY // This is the usual method eventAdmin.postEvent(pokedEvent); } else { // send SYNCHRONOUSLY // Can cause delays in application execution waiting for event to execute eventAdmin.sendEvent(pokedEvent); } return true; } }