• Bug
  • Status: Resolved
  • 2 Major
  • Resolution: Fixed
  • ehcache-core
  • interfaces
  • Reporter: cchesser
  • September 20, 2012
  • 0
  • Watchers: 6
  • June 06, 2013
  • October 01, 2012

Description

When using addCacheIfAbsent from CacheManager for a cache which is not externally configured with ehcache.xml, there is an opportunity for a net.sf.ehcache.ObjectExistsException to occur, stating “Cannot create cache: XYZ with the same name as an existing one”. The stack trace which is associated to this exception is:

Caused by: net.sf.ehcache.ObjectExistsException: Cannot create cache: XYZ with the same name as an existing one.
	at net.sf.ehcache.config.Configuration.addCache(Configuration.java:916)
	at net.sf.ehcache.config.CacheConfiguration.registerCacheConfiguration(CacheConfiguration.java:1650)
	at net.sf.ehcache.config.CacheConfiguration.setupFor(CacheConfiguration.java:1549)
	at net.sf.ehcache.CacheManager.initializeEhcache(CacheManager.java:1234)
	at net.sf.ehcache.CacheManager.addCacheNoCheck(CacheManager.java:1289)
	at net.sf.ehcache.CacheManager.addCacheIfAbsent(CacheManager.java:1762)
	at net.sf.ehcache.CacheManager.addCacheIfAbsent(CacheManager.java:1785)

It appears that CacheConfiguration.registerCacheConfiguration(…), will attempt to add to the Configuration via addCache(…) which will fail if something has already been configured. Therefore, if you are attempting to get access to your cache through addCacheIfAbsent in a multi-threaded environment, you can have the chance where the check for configuration in registerCacheConfiguration may return not-null, and attempt to add it, but right after this check and prior to adding it, another thread adds to the configuration which will fail here (within addCache, checking the cacheConfigurations map):

        if (cacheConfigurations.get(cacheConfiguration.name) != null) {
            throw new ObjectExistsException("Cannot create cache: " + cacheConfiguration.name + " with the same name as an existing one.");
        }

Here is an example test which causes this exception:

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import net.sf.ehcache.CacheManager;

import org.junit.Test;


public class AddCacheIfAbsentTest {

    private static final String CACHE_NAME = "test-cache";

    @Test
    public void test_10000_Executions() throws InterruptedException {
        final Executor executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000; i++) {
            executor.execute(new CreateAndRemoveCache());
        }
    }

    public class CreateAndRemoveCache implements Runnable {

        public CreateAndRemoveCache() {
        }

        @Override
        public void run() {
            final CacheManager cm = CacheManager.getInstance();
            cm.addCacheIfAbsent(CACHE_NAME);
            cm.removeCache(CACHE_NAME);
        }
    }
}

Comments

Carl Chesser 2012-10-03

@Chris Dennis, what version is this fixed? Where should I be looking up DEV-8265 (as it isn’t an Ehcache Core issue)? Thanks.

Chris Dennis 2012-10-03

It’s fixed in revision 6374 which currently hasn’t been merged to anywhere other thank trunk. Given this issue’s current target (Vicente) it won’t get released until early next year (although there will be beta releases before then). It’s possible that this gets retargeted for a future dot release on either 2.6.x or 2.5.x but that hasn’t happened yet.

DEV-8265 is a private JIRA filed by a TC employee who discovered the same issue. It’s been marked and closed as a duplicate - it doesn’t have any more information on it than this issue does.

Carl Chesser 2012-10-03

OK, thanks for the added information.

Carl Chesser 2012-12-19

Appears this issue is resolved in 2.6.2.

Krashan Brahmanjara 2013-06-06

The same problem exist for default cache configuration and is not fixed in 2.6.6 and 2.7.0 {noformat} Caused by: net.sf.ehcache.ObjectExistsException: Cache xxx already exists at net.sf.ehcache.CacheManager.addCache(CacheManager.java:1171) {noformat}

Main problem is in calls addCacheNoCheck with strict=true - strict=false is better.