Since my last article about springframework and hippo “Roadtrip from springframework to hippo 7” I have made a lot of changes to the code and moved my project to the hippo forge. With this post I want to explain what I have changed and in some situations why. I will not repeat the stuff I already talked about in the previous post. One of the biggest areas I made changes in, is the stability of the solution. I used the Circuit Breaker implementation as discussed by Allard in his post “Bring some stability to your architecture“. Stability comes with reconnect options and a component that guards the repository. In case of to many errors the connections are closed and after a certain cool down period, new connections are created.
One remark I like to make is about the connection pool. This pool is probably not production ready. I did not do any performance tests and it is a bit rough around the edges.
That said, let’s move on and start talking about the solution.
Overview
Let’s start of with an overview of the problem domain. You have a running hippo repository, you can use the cms to edit content, the console to configure the details, the site toolkit to create a site and maven to bundle it all together. Now you have a website (maybe an existing, maybe a new one) that needs to serve content from the repository. Or you want to expose the content using an rss feed, or maybe even a web service. The sample application that you can find on the forge of hippo uses a web service to demonstrate the capabilities.
To be able to connect and interact with the hippo repository (over rmi), you need two jar files: hippo-ecm-api.jar and hippo-ecm-repository-connector.jar. Using these jars and a bit of spring wiring, You can create a wrapper layer around the Hippo repository connection.
The following image shows the classes we need for interacting with the repository. The SessionFactory uses the class org.hippoecm.repository.HippoRepositoryFactory
to get a reference to the hippo repository. With this reference new sessions can be created. So that’s it? No not really. For performance reasons we want to reuse session when they are only used for read only actions. We also want to recover from connection problems and we want a mechanism to listen for specific events in the repository.
Session pooling
To be able to do more with sessions, we wrap the standard javax.jcr.Session
. The interface we expose is different than the standard session. This enables us to create a common interface for normal obtained sessions and pooled sessions. An important method for pooled sessions is the close method. For normal sessions, this means logout, for pooled sessions this means return to the pool.
Obtaining a session from the pool is done via the DefaultHippoSessionPool
using the interface HippoSessionPool
. To be able to initialize the pool and to clean it, two methods are exposed as well. This enables you to re-initialize the pool when for instance the connection was broken.
Listening to the repository
When creating an external application it might be interesting to know what happens in the repository. That is why the event listener is available. The SessionListenerService
accepts RepoEventListener
objects and notifies them of events taking place in the repository. The service uses a session to register the listeners. Do remember that the listeners are registered over an rmi connection. If the connection dies, the listeners will not receive events.
Session Manager
In order to handle broken connections, starting up pools, re-registering listeners and provide an easy interface to obtain read-only as well as normal sessions, we have the SessionManager
. The SessionManager initializes the pool and registeres the listeners. It also closes the pool and tries to de-register listeners when closing down or in case of problems.
The SessionManager is the class used by your code to access the repository. An example is the BaseQueryTemplateAdapter
that uses the SessionManager to easily query the repository for a search string.
CircuitBreaker
We already talked about broken connections, re-initializing the pool, re-registering the listners. How do we know the connection is broken? This is less obvious than you expect. Especially for the listeners. A session can be checked for liveness, but the listeners are not in a normal synchronous process. The listeners are also not notified of broken connections. Therefore we have introduced the circuit breaker that takes away part of the pain. The following image gives you an overview of the circuit breaker implementation. If you want to read more about the circuit breaker in general, read the post from Allard.
So how does it work? The mothods in the HippoSessionFactory are annotated with the @Monitored tag. That way the aspect AnnotatedMethodCircuitBreakerInterceptor
wraps all method calls to create a new session. If errors occur it might cause the CircuitBreaker implementation to move to OPEN state. After the cooldown period, a connection is tried again. If that connection succeeds, the state is changed to CLOSED again. All registered listeners of type StateChangeListener
are notifed. The SessionManager
also implements the StateChangeListener interface. That way the CircuitBreaker notifies the SessionManager when the state is changed. The SessionManager uses this information to re-initialize the session pool and re-register the listeners.
Last remarks
That’s it for this post. I hope it is clear how you can connect to hippo using spring by now. Hippo provides documentation on this topic itself as well. If you want to try this out, go to the hippo website below. Look for the quickstart. Run the repository and fire up the sample I have provided. For more information about the webservice, check my previous post.
References
- https://www.gridshore.nl/2008/12/04/roadtrip-from-springframework-to-hippo-7/
- https://www.gridshore.nl/2008/10/30/bring-some-stability-to-your-architecture/
- http://docs.onehippo.org/
- http://www.onehippo.org/cms7/delve_into/quickstart.html
- http://forge.onehippo.org/projects/soap-exposure/