Using EhCache in Spring 4 without XML Using EhCache in Spring 4 without XML java java

Using EhCache in Spring 4 without XML


XML-less configuration of EhCache in Spring

@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer {    @Bean(destroyMethod="shutdown")    public net.sf.ehcache.CacheManager ehCacheManager() {        CacheConfiguration cacheConfiguration = new CacheConfiguration();        cacheConfiguration.setName("myCacheName");        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");        cacheConfiguration.setMaxEntriesLocalHeap(1000);        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();        config.addCache(cacheConfiguration);        return net.sf.ehcache.CacheManager.newInstance(config);    }    @Bean    @Override    public CacheManager cacheManager() {        return new EhCacheCacheManager(ehCacheManager());    }    @Bean    @Override    public KeyGenerator keyGenerator() {        return new SimpleKeyGenerator();    }    @Bean    @Override    public CacheResolver cacheResolver()    {        return new SimpleCacheResolver();    }    @Bean    @Override    public CacheErrorHandler errorHandler() {         return new SimpleCacheErrorHandler();    }}

Alternatively for testing, you can use a simple ConcurrentMapCache running without XML as below.

@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer {    @Bean    @Override    public CacheManager cacheManager() {        SimpleCacheManager cacheManager = new SimpleCacheManager();        List<Cache> caches = new ArrayList<Cache>();        caches.add(new ConcurrentMapCache("myCacheName"));        cacheManager.setCaches(caches);        return cacheManager;    }    @Bean    @Override    public KeyGenerator keyGenerator() {        return new SimpleKeyGenerator();    }    @Bean    @Override    public CacheResolver cacheResolver()    {        return new SimpleCacheResolver();    }    @Bean    @Override    public CacheErrorHandler errorHandler() {         return new SimpleCacheErrorHandler();    }}

Edit: Updated to add shutdown method on underlying cache

Edit: Added configuration for error handler and cache resolver

Edit: changing constructor call on SimpleCacheResolver which resolves CacheManager must not be null issue (Spring v5.1+)

@Configuration@EnableCachingpublic class CachingConfig implements CachingConfigurer {    public static final String USER_CACHE_INSTANCE = "my-spring-ehcache";    private final CacheManager cacheManager;    private final net.sf.ehcache.CacheManager ehCacheManager;    public CachingConfig() {        CacheConfiguration cacheConfiguration = new CacheConfiguration();        cacheConfiguration.setName(USER_CACHE_INSTANCE);        cacheConfiguration.setMemoryStoreEvictionPolicy("LRU");        cacheConfiguration.setMaxEntriesLocalHeap(1000);        net.sf.ehcache.config.Configuration config                = new net.sf.ehcache.config.Configuration();        config.addCache(cacheConfiguration);        this.ehCacheManager = net.sf.ehcache.CacheManager.newInstance(config);        this.cacheManager = new EhCacheCacheManager(ehCacheManager);    }    @Bean(destroyMethod="shutdown")    public net.sf.ehcache.CacheManager ehCacheManager() {        return ehCacheManager;    }    @Bean    @Override    public CacheManager cacheManager() {        return cacheManager;    }    @Bean    @Override    public KeyGenerator keyGenerator() {        return new SimpleKeyGenerator();    }    @Bean    @Override    public CacheResolver cacheResolver() {        return new SimpleCacheResolver(cacheManager);    }    @Bean    @Override    public CacheErrorHandler errorHandler() {        return new SimpleCacheErrorHandler();    }}


I do this at two levels of abstraction, a configuration file per technology (Ehcache, Redis, etc.) and a general configuration file.

Here's the one for Ehcache (Redis would be similar):

@Configurationpublic class EhCacheConfiguration {    @Bean    public EhCacheCacheManager ehCacheCacheManager() {        return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());    }    @Bean    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {        EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();        cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));        cacheManagerFactoryBean.setShared(true);        return cacheManagerFactoryBean;    }}

And here's the general one (complete with Redis hooks):

@Configuration@EnableCachingpublic class CachingConfiguration implements CachingConfigurer {    @Qualifier("ehCacheCacheManager")    @Autowired(required = false)    private CacheManager ehCacheCacheManager;    @Qualifier("redisCacheManager")    @Autowired(required = false)    private CacheManager redisCacheManager;    @Bean    @Override    public CacheManager cacheManager() {        List<CacheManager> cacheManagers = Lists.newArrayList();        if (this.ehCacheCacheManager != null) {            cacheManagers.add(this.ehCacheCacheManager);        }        if (this.redisCacheManager != null) {            cacheManagers.add(this.redisCacheManager);        }        CompositeCacheManager cacheManager = new CompositeCacheManager();        cacheManager.setCacheManagers(cacheManagers);        cacheManager.setFallbackToNoOpCache(false);        return cacheManager;    }    @Bean    @Override    public KeyGenerator keyGenerator() {        return new DefaultKeyGenerator();    }}