EhCache - Using Multiple CacheManagers

Well until today in my posts about EhCache I've always been talking and assuming of using only one CacheManager, by specifying SingletonEhCacheProvider as the cache provider for Hibernate. But there are situations when you would not be able(or not want to use SingletonEhCacheProvider). Say for example you would have two Hibernate connections for two different database connections and you want to keep things separate in two cache managers each with it's own ehcache.xml config file.
I'm going to show you how this can be done. You can skip right to the short list at the the end, or read the detailed thing.
[sourcecode language="xml"] org.hibernate.dialect.MySQL5Dialect true true

            <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>    <!-- this instead of SingletonEhCacheProvider -->
            <prop key="net.sf.ehcache.configurationResourceName">ehcache.xml</prop> <!-- this way you can specify the location of the config file for every CacheManager -->
        </props>
    </property>

[/sourcecode]

Well when using SingletonEhCacheProvider and doing our thing of getting the CacheManager instance.
[sourcecode language="java"] CacheManager cacheManager = CacheManager.getInstance(); [/sourcecode] We see in the log
[sourcecode language="text"] 2010-02-22 WARN net.sf.ehcache.CacheManager - Creating a new instance of CacheManager using the diskStorePath "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\" which is already used by an existing CacheManager.
[/sourcecode] So we see that a new CacheManager is being created by our call of CacheManager.getInstance(). Since we do not actually want to create a new instance of a CacheManager, but to access one of the caches, we need a way of first obtaining the right CacheManager from which to obtain the desired cache. Well CacheManager has a static ALL_CACHE_MANAGERS member variable which is actually the list of ... you guessed it - ALL the CacheManagers you started(or Hibernate did for you).

public class CacheManager {  
    public static final List<CacheManager> ALL_CACHE_MANAGERS = new CopyOnWriteArrayList<CacheManager>();
....
}

The problem still remains on how to actually obtain your desired CacheManager from this list containing ALL of them. There must be a way to distinguish between them, and there is actually the simplest way of doing this, by setting a name to your CacheManager and then look through the list for the CacheManager with that name. The problem is that it's not evident how to set this name. If we browse through the source code, we see that the name of the CacheManager is actually taken from the ehcache.xml config file, and so we should specify it there.

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
             updateCheck="true" name="myCacheManager">
....

Now we can maybe save it in a static variable so maybe save the time on lookup.

public class CacheUtil {  
  public static CacheManager myCacheManager;

  public CacheManager getMyCacheManager() {
    if(myCacheManager == null) {
    for (CacheManager cacheManager : CacheManager.ALL_CACHE_MANAGERS) {
       if("myCacheManager".equals(cacheManager.getName())) {
          myCacheManager = cacheManager;
       }
    }
    return myCacheManager;
  }
}
Short list
  1. We want not to use more than one CacheManager so SingletonCacheManager not an option.
  2. solution: use as the cache provider for Hibernate EhCacheProvider
  3. problem: call of CacheManager.getInstance() creates new instance of a CacheManager instead of giving the singleton instance as in the case. Need another way of getting the right CacheManager
  4. solution: use CacheManager.ALL_CACHE_MANAGERS which is a list of CacheManagers
  5. CacheManager has a name property which we can use to get the right CacheManager from the ALL_CACHE_MANAGERS list.
  6. ehcache.xml can be used to set the property name of the CacheManager
comments powered by Disqus