Created

Jan 10, 2013

Using Event filters for handling JCR events through an event handler.

Posted by Nicolas Peltier

In a previous post, i was explaining how to handle events generally, with several solutions among which:

  • jcr observer
  • sling event handler

a distinction was made between both around the fact jcr observers are low level, but allow to do more. While this is still true :-) this POST will explain how to do a fine-grained jcr event listening through sling event handler (and take profit of the sling event handling framework for those events).

While in jcr, everything is content, in sling, everything is a resource, so instead of listening to node/property added/removed we'll listen to resource changed, through the 3 topics :

  1. SlingConstants.TOPIC_RESOURCE_ADDED,
  2. SlingConstants.TOPIC_RESOURCE_CHANGED,
  3. SlingConstants.TOPIC_RESOURCE_REMOVED

Now we should have a handler that listens for all the repository, for those -very common- events, which will certainly be a performance killer. Thus we need to filter out this by adding osgi event filtering

This EventConstants.EVENT_FILTER property takes LDAP filter syntax, and has a path attribute, so we can do e.g. (path=/content/my/root/*) or even (path=/content/my/root/*/myNode).

 

A sample code would then be :

@Component
@Service(value=EventHandler.class)
@Properties({
 @Property(name= EventConstants.EVENT_TOPIC,value= {SlingConstants.TOPIC_RESOURCE_ADDED,SlingConstants.TOPIC_RESOURCE_CHANGED, SlingConstants.TOPIC_RESOURCE_REMOVED}),
 @Property(name=EventConstants.EVENT_FILTER,value="(path=/content/my/root/*/myNode)")
})
public class ExampleServiceImpl implements EventHandler { 
 final String[] eventProps = { "resourceAddedAttributes", "resourceChangedAttributes", "resourceRemovedAttributes" };

 public void handleEvent(org.osgi.service.event.Event event) {
  for (String eventProp : eventProps){
   String[] props = (String[])event.getProperty(eventProp);
   …
 }		
}

Pros of this approach vs. Jcr Observer are : 

  • this is simpler.
  • this is cluster ready.
  • you have the user id information in it (userid attribute of the event).

A con i can see is that in the particular case of a bulk save done of N concerned resources, your handler will be called N times, and then if your handler does persist, you'll have a total of N (handler persistences) + 1 (bulk save) persistences done. While with a jcr observer, you can loop through all the changes of the transaction, and do another batch save, reducing the persistences to 2.