Search code examples
javajakarta-eenullpointerexceptionehcacheehcache-3

Exception in Ehcache when trying to remove all the caches


I already searched for the solution as other question has also posted java.lang.NullPointerExcpetion.But i am not able to find my problem.I am using Ehcache 3 and I have instantiated a cache which is putting the data into the cache.

The class which is working as Cache is:

import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.ResourceType;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.expiry.Duration;
import org.ehcache.expiry.Expirations;

import javax.ejb.Stateless;
import javax.enterprise.inject.spi.CDI;
import java.io.File;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;


public class CacheHelper {

    private CacheManager cacheManager;

    private Cache<String,GenericClassForMap> mapPerson;


    private static Timer timer;

    public CacheHelper() {
        timer = new Timer();
        TimerTask task = new Helper();

        timer.schedule(task, 2, 5000);

    }

    //initialziing cache
    public void putInCacheFromDb() {
        System.getProperties().setProperty("java -Dnet.sf.ehcache.use.classic.lru", "true");
        cacheManager= CacheManagerBuilder
                .newCacheManagerBuilder().build();
        cacheManager.init();

        //for map
        mapPerson = cacheManager
                .createCache("cacheOfmap", CacheConfigurationBuilder
                        .newCacheConfigurationBuilder(
                                String.class,GenericClassForMap.class,
                                ResourcePoolsBuilder.heap(100000)).withExpiry(Expirations.timeToLiveExpiration(Duration.of(60000,
                                TimeUnit.SECONDS))));
        Map<Integer,Person> mp=new HashMap<>();
        mp.put(1,new Person(1,"om"));

        mapPerson.put(CACHE_MAP_PARAMETER,new GenericClassForMap(mp));

    }

    //method to clear the cache
    public void clearAllCache(){
        System.out.println("cache is being cleared........");
          cacheManager.close();
      }

}

The data is being inserted in the cache when i run the program and is printed as:

 coming from map
[Person{id=1, name='om'}]

I am putting the timer for cache and in 15second the cache needs to be refreshed.So,I tried using the Helper.java class as,

import com.cache.cachemanager.CacheHelper;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;


public class Helper extends TimerTask
{
    public static int i = 0;

    public void run()
    {
        System.out.println("Timer ran " + ++i);

        if(i==15){
            try {

                Thread.sleep(10000);
                System.out.println("system is sleeping");
                CacheHelper cacheHelper=new CacheHelper();
                cacheHelper.clearAllCache();
               cacheHelper.putInCacheFromDb();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }
    }
}

I am getting null pointer exception at:

system is sleeping
 cache is being cleared........
Exception in thread "Timer-6" java.lang.NullPointerException
   at com.cache.cachemanager.CacheHelper.clearAllCache(CacheHelper.java:309)
  at com.cache.timer.Helper.run(Helper.java:25)

I tried to debug the program and I am seeing the null pointer exception is coming from :

 cacheManager.close();

My cacheManager is being null.But When I try to clear the cache from API request,it is able to clear the cache.I am not using spring framework.Why is my cacheManager being null but it is being removed easily when called through API Like:

http://localhost:8080/myresource/clearCache ,my cache is being cleared easily.

cache is being cleared........
11:19:31,154 INFO  [org.ehcache.core.EhcacheManager] (default task-8) Cache 'cacheOfmap' removed from EhcacheManager.

Solution

  • Before calling your clearAllCache method, you created a new CacheHelper(). Thus, the cacheManager attribute of this instance is never initialized (you intiliaze it only in the putInCacheFromDb method).
    I guess when you call it through API, you have a bean/singleton instance that was called to fill your cache and is then never destroyed. So this instance must be used.

    EDIT : To answer the question Why initialize cacheManager in the constructor.
    Your current code runs as following :

        // CacheHelper constructor is called to initialize a new CacheHelper
        // => cacheManager attribute is not initialized
        CacheHelper cacheHelper = new CacheHelper();
        // This method will call cacheManager.close().
        // => cacheManager is currently null => NullPointerException
        cacheHelper.clearAllCache();
        // This method will initialize the cacheManager attribute
        // => Too late the Exception already occured
        // => So, need to initialize cacheManager attribute before calling clearAllCache()
        // => the constructor is the best place to do this here.
        cacheHelper.putInCacheFromDb();