Friday 22 August 2014

Ehcache CacheManager with same name already exists in the same VM

keys: Java, Ehcache, CacheManager name, multiple configurations

Straight to the point:

Explicitly providing a CacheManager name in an Ehcache configuration file allows to avoid the "CacheManager with same name already exists in the same VM" error after upgrading to Ehcache version 2.5 and later.
The CacheManager name should be specified in each Ehcache config file via the name attribute of the top-level ehcache element, for example:

ehcache.xml
<ehcache name="http-filter-cache"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcahce.xsd">
    <defaultCache />
</ehcache>
This works regardless whether a singleton or multiple instances of CacheManager are created.

In detail:

Ehcache is a widely used open-source caching solution for enterprise Java applications.
Most known examples, perhaps arguably, would be using Ehcache as a second-level Hibernate cache and the cache implementation in Apache Camel.
Version 2.5 was enhanced with a new feature called Automatic Resource Control. The ARC (finally) allowed to specify heap and disk allocations in bytes rather than in elements (as well as for Off Heap storage).

Problem:
After upgrading a Java web application to take advantage of the new version, we encountered a problem that manifested in failures of numerous JUnit tests. Launching the web application also started to fail.

Examining log files revealed the following error message:

CacheManager with same name already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:

1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.

The application included 2 Ehcache configuration files each containing a default cache definition as well as several other named caches. At first, a suspicion was that the problems were caused by having more than one default cache (each file contains a default cache definition). Since the default caches are unnamed, there might have been a collision. That's however proved to be a totally wrong lead.

Proceeding to examine the source code of net.sf.ehcache.CacheManager class, we came across this javadoc comment in class constructors:

Since 2.5, every newly created CacheManager is registered with its name (uses a default name if unnamed), and trying to create multiple CacheManager with same names (or multiple unnamed CacheManagers) is not allowed and throws an exception.

Looking further into the source code and stepping in with the debugger, we discovered that CacheManager now maintains a static Map<String, CacheManager> class variable to store every instance of the class created in the JVM using the name specified in a configuration as the key (the map is named CACHE_MANAGERS_MAP as of version ehcache-core 2.6.9).

All constructors and the factory methods utilize the map to return a CacheManager object according to the specs. The CacheManager provides two kinds of instantiation modes: creating a new instance on each call or returning an existing object (singleton). (More on CacheManager creation modes can be found on a Ehcache website).

Regardless of the creation mode, i.e. instance or singleton, the CacheManager name must be unique.

Surprisingly, considering that the change is quite well documented, the Ehcache documentation does not spell out, at least not readily, how to assign a name to a CacheManager instance.
The answer was found in the ehcache.xsd schema that specifies the optional name attribute for the ehcache element:
<xs:schema>
    <xs:element name="ehcache">
        <xs:complexType>
            <xs:attribute name="name" use="optional"/>
            <xs:sequence>
                <xs:element maxOccurs="1" minOccurs="0" ref="diskStore"/>
                ...
            </xs:sequence>
            ...
When the name attribute is specified for the the top-level ehcache element, a CacheManager constructor will use its value as the name for the CacheManger instance and as the key when registering the object in the static CACHE_MANAGERS_MAP map. Otherwise, i.e. when the name attribute is omitted, CacheManager will use a default value, __DEFAULT__, as the name. If the app is designed to use a single ehcache configuration, it will not cause any trouble. However, there are cases when it's preferable to use multiple cache configuration files. In which case it will result in the error when the name attribute is not used.

To avoid the problem, each Ehcache configuration should specify a name. The fragment from a configuration file below is an example:
<ehcache name="http-filter-cache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocaton="ehcache.xsd">
   <!-- CacheManager configuration
       (omitted from the sample)
   />
</ehcache>
And in conclusion, a friendly suggestion to the Ehcache development team: maybe the name attribute should be made mandatory rather than optional to avoid the problem described in this post.

No comments:

Post a Comment