Sign in

E-mail *, (xx@domain.com)
Password *

Register | Forgot password

Blogs

  • Bram de Kruijff
  • Ivo Ladage
  • Mark van Cuijk
  • Martin van Mierloo
  • Martijn van Berkum
  • Michel Teunissen
  • Patrick Atoon

Recent blogs

RSS - Blogs
March 9, 2010
State of OSGi in the Java world
March 4, 2010
Reach more people with Google Translate
March 3, 2010
Get My Advice
February 26, 2010
What? Where!?!
February 11, 2010
Split it!

All Blogs...


Big Brother is watching

February 29, 2008

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.


The use case


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.


Preparing a service for observation


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.


Handling individual events


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.



About the Author

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:

March 3, 2010
Get My Advice
February 11, 2010
Split it!
April 22, 2009
What goes in, must come out!
July 29, 2008
WCB Sharing FTW!
June 17, 2008
Found me on LinkedIn?
April 18, 2008
Tosti
April 7, 2008
Baking apple pie at 347
March 21, 2008
Short story about not inventing another wheel
March 13, 2008
Files in and files out


Share:

del.icio.us
digg
Technorati
Slashdot
Reddit
YahooMyWeb
NewsVine
ekudos
© 2010 GX creative online development B.V.

Disclaimer

This website (GXdeveloperweb.com) may discuss or contain opinions, (sample) coding, software or other information that does not include GX official interfaces, instructions or guidelines and therefore is not supported by GX. Changes made based on this information are not supported.  GX will not be held liable for any damages caused by using or misusing the information, software, instructions, code or methods suggested on this website, and anyone using these methods does so at his/her own risk. GX offers no guarantees and assumes no responsibility or liability of any type with respect to the content of this website, including any liability resulting from incompatibility between the content of this website and the materials and services offered by GX. By using this website you will not hold, or seek to hold, GX responsible or liable with respect to the content of this website.