Getting started with Ehcache 2.X with a simple demo.

Ehcache is an open-source, standards-based cache for boosting performance, offloading your database, and simplifying scalability. As a robust, proven, and full-featured solution, it is today’s most widely used Java-based cache. You can use Ehcache as a general-purpose cache or a second-level cache for Hibernate.

Here let me explaing how to use Ehcache with a simple mutithreading program.Lets start with dependencies required,Below are the depdendecies required to use Ehcache.


        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.5.6</version>
        </dependency>


Configuration XML :
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
         monitoring="autodetect" dynamicConfig="true">

    <diskStore path="java.io.tmpdir"/>

    <cache name="cache1"
           maxEntriesLocalHeap="1000"
           maxEntriesLocalDisk="10000"
           eternal="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="60"
           timeToLiveSeconds="300"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
        <persistence strategy="localTempSwap"/>
    </cache>

    <cache name="cache2"
           maxEntriesLocalHeap="1000"
           maxEntriesLocalDisk="10000"
           eternal="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="120"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           transactionalMode="off">
        <persistence strategy="localTempSwap"/>
    </cache>

</ehcache>



Let me brieflly explain about attributes of Cache tag

  1. maxEntriesLocalHeap : Maximum no of elements allowed in memory.
  2. maxEntriesLocalDisk : Once Heap is full,then element overflow to disk memory.So this is maximum no of elements allowed in Disk.
  3. eternal : Sets whether elements are eternal. If eternal,  timeouts are ignored and the element is never expired.
  4. diskSpoolBufferSizeMB : This is the size to allocate the DiskStore for a spool buffer. Writes are made
        to this area and then asynchronously written to disk. The default size is 30MB.
  5. timeToIdleSeconds : Element will expire if idle time reachs to timeToIdleSeconds(in seconds).
  6. timeToLiveSeconds : Element will expire if life of the element reachs to timeToIdleSeconds(in seconds).
  7. memoryStoreEvictionPolicy : Policy would be enforced upon reaching the maxEntriesLocalHeap limit. Default policy is Least Recently Used (specified as LRU). Other policies available - First In First Out (specified as FIFO) and Less Frequently Used (specified as LFU)
  8. transactionalMode :  To enable an ehcache as transactions, set the transactionalMode.
  9. diskStore : If heap memory is full,then elements overflow to disk.Diskstore is the path of disk directory.

There are many such attributes in xml configuration,please go through ehcache schema definition.


User Model Class :
public class User implements Serializable{

    private Integer userid;
    private String username;
    private String password;
    private String role;
    private Integer tenantid;

    public User(Integer userid, String username, String password, String role, Integer tenantid) {
        this.userid = userid;
        this.username = username;
        this.password = password;
        this.role = role;
        this.tenantid = tenantid;
    }

//setters & getters

}

CachedUserManager :

CachedUserManager will intract with cache and do CRUD operations on cache.

public class CachedUserManager<K extends Integer, V extends User> {

    private final Cache cache;

    public CachedUserManager(Cache cache) {
        this.cache = cache;
    }

    public void add(K k, V v) {
        cache.put(new Element(k, v));
    }

    public V getValue(K k) {
        return (V) cache.get(k).getObjectValue();
    }

    public boolean keyExist(K k) {
        return cache.get(k) == null ? false : true;
    }

    public void deleteElement(K k) {
        if (cache.get(k) != null) {
            cache.remove(k);
        }
    }

    public Cache getCache() {
        return cache;
    }
}

UserEhcacheDemo :

Here is the Demo code to add user objects into cache.This demo will explaing how to add User object to cache and making current thread to sleep, so that idle time of user objects reachs to timeToIdleSeconds(specified in xml) hence objects status will changed to expire and removed from cache.


public class UserEhcacheDemo {


    public static final String CACHE_1 = "cache1";
    public static final String CACHE_2 = "cache2";

    public static void main(String[] args) {

        CacheManager cacheManager = buildCacheManager();
        Cache cache1 = getCache1(cacheManager);
        Cache cache2 = getCache2(cacheManager);
        final CachedUserManager cachedUserManager1 = new CachedUserManager<Integer, User>(cache1);
        final CachedUserManager cachedUserManager2 = new CachedUserManager<Integer, User>(cache2);

        int noOfThreads = 2;
        ExecutorService execService = Executors.newFixedThreadPool(noOfThreads);
        execService.submit(new Runnable() {
            String threadName = "thread_1";
            @Override
            public void run() {
                //adding some users to cache1
                addUsersToCache(cachedUserManager1,threadName);

                //retrieve users from cache1
                Integer i = new Integer(1);
                while(i<5)
                {
                    //any random value between 1 to 45 sec
                    int sleepTime = getRandomSleepTime(1000, 45000);
                    System.out.println(threadName +" will sleep during "+sleepTime+" milliseconds");
                    try {
                        Thread.currentThread().sleep(sleepTime);
                    }catch (InterruptedException e)
                    {
                        //do nothing
                    }
                    boolean exist = cachedUserManager1.keyExist(i);
                    System.out.println("user"+i+ (exist?" exist":" not exist")+ " in cache1 with "+threadName);
                    i++;
                }


            }
        });
        execService.submit(new Runnable() {
            String threadName = "thread_2";
            @Override
            public void run() {
                //adding some users to cache2
                addUsersToCache(cachedUserManager2,threadName);

                //retrieve users from cache1
                Integer i = new Integer(1);
                while(i<5)
                {
                    //any random value between 30 to 60 sec
                    int sleepTime = getRandomSleepTime(30000, 60000);
                    System.out.println(threadName +" will sleep during "+sleepTime+" milliseconds");
                    try {
                        Thread.currentThread().sleep(sleepTime);
                    }catch (InterruptedException e)
                    {
                        //do nothing
                    }
                    boolean exist = cachedUserManager2.keyExist(i);
                    System.out.println("user"+i+ (exist?" exist ":" not exist ")+ "in cache2 with "+threadName);
                    i++;
                }
            }
        });

    }

    public static Cache getCache1(CacheManager cacheManager) {
        return cacheManager.getCache(CACHE_1);
    }

    public static Cache getCache2(CacheManager cacheManager) {
        return cacheManager.getCache(CACHE_2);
    }

    public static CacheManager buildCacheManager() {
        InputStream is = UserEhcacheDemo.class.getClassLoader().getResourceAsStream("com/ehcache/userCache.xml");
        return CacheManager.create(is);
    }

    private static void addUsersToCache(CachedUserManager cachedUserManager,String threadName) {
        Integer i = new Integer(1);
        while(i<5){
            cachedUserManager.add(i, new User(i, "user" + i, "password" + i, "role" + i, i));
            System.out.println("Added user"+ i + " to "+ cachedUserManager.getCache().getName() + " using " + threadName);
            i++;
        }
    }

    private static int getRandomSleepTime(int min, int max){
        return min + (int)(Math.random() * ((max - min) + 1));
    }

}


Above program will have mutiple outputs,Here is one among them

Added user1 to cache2 using thread_2
Added user2 to cache2 using thread_2
Added user3 to cache2 using thread_2
Added user4 to cache2 using thread_2
thread_2 will sleep during 37461 milliseconds
Added user1 to cache1 using thread_1
Added user2 to cache1 using thread_1
Added user3 to cache1 using thread_1
Added user4 to cache1 using thread_1
thread_1 will sleep during 11195 milliseconds
user1 exist in cache1 with thread_1
thread_1 will sleep during 12607 milliseconds
user2 exist in cache1 with thread_1
thread_1 will sleep during 16771 milliseconds
user1 exist in cache2 with thread_2
thread_2 will sleep during 44240 milliseconds
user3 exist in cache1 with thread_1
thread_1 will sleep during 10718 milliseconds
user4 exist in cache1 with thread_1
user2 exist in cache2 with thread_2
thread_2 will sleep during 56851 milliseconds
user3 not exist in cache2 with thread_2
thread_2 will sleep during 41211 milliseconds
user4 not exist in cache2 with thread_2



In the Demo program,we have two threads adding 4 users to respective cache.After adding users,trying to retrieving users from cache.While retrieving, threads to going to sleep.Sleep time is randomly calculated as mentioned in the program.If you remember we kept idle time to 1 and 2 mins in respective cache configuration.So if thread sleep for more then 1 min with out reading elements then such elements will expire and removed from cache.
In the above output, users like user4 not exist in cache1 and user3,user4 not exists in cache2.It mean idle time reached for these users,so expired.

You can download source from GitHub.

Show Comments: OR

0 comments: