Register | Forgot password
All Blogs...
Starting with WebManager 9, most data is stored in the Java Content Repository. This has a lot of advantages, most of which were intended, but some are a nice bonus. A couple of weeks ago I found a nice feature in the JCR API called the ObservationManager, which basically provides an interface to asynchronously monitor changes made to nodes in the JCR.
At that moment I was working on a project for the regional police department in Utrecht, who required mail notifications to be sent when certain actions were performed. I noticed a perfect fit in this case, so I wrote a design, retrieved an approval and implemented a solution using the ObservationManager.
One part of the project was the need to maintain information in the form of messages that, at first, are bounded to a certain geographical district. After some time it might happen that a certain message applies to more than one district, so the message needs to be propagated to other districts. At the user interface this is performed by checking a check box for each district to propagate the message to. By saving the page, an additional node is added to the JCR, which links the message to another district.
At the moment this happens, an email notification is sent to the main editor(s) of the receiving district(s), so they can decide to accept or deny the new message. Although not a requirement, I wanted the user interface to be fast, even in the case that multiple notifications had to be sent. For that reason, an asynchronous solution would be preferred and the ObservationManager offers just that.
As a good engineering practice of function decoupling, I created a new service to place the notification code into. From the activator I defined three dependencies: one for interacting with another service in the WCB, one for the ConfigurationManagement to obtain the SMTP hostname and one on the JcrRepository to access the JCR and the ObservationManager. In the service I defined a private javax.jcr.Session observationSession field and the start() and stop() methods that the DependencyManager calls when I can start listening for changes or when I should stop doing it.
public void start() throws RepositoryException {
try {
observationSession = jcrRepository.createSystemSession();
ObservationManager observationManager =
observationSession.getWorkspace().getObservationManager();
MessageListener listener = new MessageListener();
observationManager.addEventListener(listener,
Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/", true, null, new String[] {LinkImpl.JCR_NODE_TYPE}, true);
} catch (RepositoryException e) {
stop();
throw e;
}
}
public void stop() {
if (observationSession != null) {
observationSession.logout();
observationSession = null;
}
}
The code it straight-forward, the magic happens at the lines where a MessageListener object is instantiated and passed to the ObservationManager uing the addEventListener() method. The MessageListener class is an inner class in the service which implements the EventListener interface.
From this point on, at the time any property of any link node is changed in the JCR, no matter how this change is done (through the service that is available for it, or by directly accessing the JCR), the onEvent() method in my EventListener is called. Because the call to this method is done directly by the JCR, there is no open WebManager session, so any use of the EntityManager and any attempt to obtain a session through the private node of a service will fail. To fix this, we must first create a WebManager session using the SessionManager. By closing this session from inside a finally clause, we ensure it will be closed nicely whatever we are going to do.
When there is an open session, all we need to do is loop over all received events, read the required information, send the email notifications and set a flag on the nodes to prevent the same notification to be sent twice.
Return to all blogs
Mark is software engineer with a special interest in Security and Digital WebTV. Mark writes about daily engineering with GX WebManager
Read all Marks blog entries
Other blog entries: