javaspringcachingehcacheterracotta

Writing a custom RefreshAheadCacheFactory with ehcache


In attempting to implment my own cache loader using inline refresh and read the docs at :

http://terracotta.org/documentation/4.1/bigmemorymax/api/refresh-ahead#scheduled-refresh-ahead

&

http://www.ehcache.org/generated/2.9.0/html/ehc-all/#page/Ehcache_Documentation_Set%2Fco-dec_creating_a_decorator_2.html

But I'm unsure how to implment my own cache. How should method createCacheLoader be implmeneted in this class :

public class MyCacheLoaderFactory extends net.sf.ehcache.loader.CacheLoaderFactory{

    @Override
    public CacheLoader createCacheLoader(Ehcache cache, Properties properties) {
        // TODO Auto-generated method stub

        return null;
    }

}

How is the CacheLoader to be returned created what how are the parameters cache & properties configured ?

I've wired up the cache in a junit using below code :

import java.util.Properties;

import net.sf.ehcache.Ehcache;
import net.sf.ehcache.loader.CacheLoader;


public class MyCacheLoaderFactory extends net.sf.ehcache.loader.CacheLoaderFactory{

    @Override
    public CacheLoader createCacheLoader(Ehcache cache, Properties properties) {
        // TODO Auto-generated method stub

        return null;
    }

}


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
    <defaultCache eternal="true" maxElementsInMemory="100"
        overflowToDisk="false" />
    <cache name="myCache" maxElementsInMemory="10000" eternal="true"
        overflowToDisk="false">

  <cacheLoaderFactory class="MyCacheLoaderFactory" 
    />

        <cacheDecoratorFactory 
            class="net.sf.ehcache.constructs.refreshahead.RefreshAheadCacheFactory"
            properties="name=myCacheRefresher,
      timeToRefreshSeconds=20,
      batchSize=10,
      numberOfThreads=4,
      maximumBacklogItems=100,
      evictOnLoadMiss=true" />

    </cache>
</ehcache>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:cache="http://www.springframework.org/schema/cache"
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <cache:annotation-driven />
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
        p:cache-manager-ref="ehcache" />
    <bean id="ehcache"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
        p:config-location="my-ehcache.xml" />

    <bean id="myCache" class="ehcache.MyCache"></bean>
</beans>

The testing classes :

package ehcache;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-ehcache.xml")
public class TestEhcache {

    @Test
    public void testCache(){

        while(true){
            System.out.println(myCache.tester());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    @Autowired
    private MyCache myCache;

}


package ehcache;

import org.springframework.cache.annotation.Cacheable;

public class MyCache {


    @Cacheable(value = "myCache")
    public String tester(){

        System.out.println("in cache");

        return "test";
    }

}

When I run test testCache I receive exception :

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [spring-ehcache.xml]: Cannot resolve reference to bean 'ehcache' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehcache' defined in class path resource [spring-ehcache.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: java.lang.NullPointerException
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)

I expect this due to my implementation of createCacheLoader just returning null but how should returned object CacheLoader be constructed ?

This is probably not relevant but here is my pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ehcache-test</groupId>
    <artifactId>ehcache-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>net.sf.ehcache.internal</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.9.0</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.1.0.RELEASE</version>
        </dependency>
    </dependencies>
</project>

Solution

  • It is up to you to return an implementation of a CacheLoader from the method in your class MyCacheLoaderFactory.

    The first parameter is the cache for which the loader is to be returned - as documented in the Javadoc for CacheLoaderFactory.createCacheLoader it is not yet initialized and so should not be used, however its configuration can be queried. This parameter is useful when you use a single factory to provide CacheLoaders to different caches.

    The second parameter is the properties that were defined in the XML configuration, same as you do with the cacheDecoratorFactory.