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 :
- SlingConstants.TOPIC_RESOURCE_ADDED,
- SlingConstants.TOPIC_RESOURCE_CHANGED,
- 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.