Make delicious recipes!

Caching Connection Factory for JMS in Spring


JMS implementations typically need some kind of connection pooling to pool connections and sessions.
CachingConnectionFactory is one such connection pool implementation provided by spring.

In this article, we go under-the-hoods of the CachingConnectionFactory and see some interesting details on the usage of dynamic-proxy.


Take a moment to browse the code for CachingConnectionFactory.
CachingConnectionFactory extends SingleConnectionFactory.
We will call CachingConnectionFactory as CCF and SingleConnectionFactory as SCF for brevity sake.

SCF.createConnection() calls targetConnectionFactory.createConnection() to get the actual JMS connection.
SCF.getSharedConnectionProxy() then wraps this real connection object into a dynamic proxy whose handler is an instance of SharedConnectionInvocationHandler.

The SharedConnectionInvocationHandler acts like a proxy for the connection and intercepts all its calls by the method:
    Object invoke(Object proxy, Method method, Object[] args)
In this method, it does a string comparison of the method-names and calls SCF.getSession() when connection.createSession() is called.

SingleConnectionFactory.getSession() simply returns null and here is when the CachingConnectionFactory comes into play.
It overrides the getSession() method and does the following:
  1. Return an existing session if its present in the existing pool
    (where pool is defined as: Map<Integer, LinkedList<Session>> cachedSessions)
  2. Otherwise return getCachedSessionProxy(createSession()) where createSession() just calls the targetConnection.createSession()
  3. getCachedSessionProxy() creates a proxy for the session using CachedSessionInvocationHandler as the invocation handler.

CachedSessionInvocationHandler handles the close() method of the session-proxy and does not redirect it to the actual Session.
Instead it just tries to do a logicalClose(). If the logicalClose() fails or number of sessions exceeds pool-size, it does a physicalClose().

logicalClose() closes only the durable topic subscribers associated with the session and then it moves the session to the end of the list.
In physicalClose(), all producers/consumers associated with the session are closed and the session is closed/removed.



References:
  1. Proxy documentation
  2. Dynamic proxies tutorial







Like us on Facebook to remain in touch
with the latest in technology and tutorials!


Got a thought to share or found a
bug in the code?
We'd love to hear from you:

Name:
Email: (Your email is not shared with anybody)
Comment:

Facebook comments:

Site Owner: Sachin Goyal