我已经在寻找解决方案,因为其他问题也发布了java.lang.NullPointerExcpetion
。但是我找不到我的问题。我正在使用Ehcache 3,并且实例化了一个将数据放入缓存的缓存
用作Cache的类是:
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();
}
}
当我运行程序时,数据正在插入缓存中,并打印为:
coming from map
[Person{id=1, name='om'}]
我为缓存设置了计时器,并且需要在15秒内刷新缓存。因此,我尝试使用Helper.java类作为
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();
}
}
}
}
我在以下位置得到空指针异常:
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)
我尝试调试程序,并且看到空指针异常来自:
cacheManager.close();
我的cacheManager为空。但是,当我尝试从API请求中清除缓存时,它可以清除缓存。我没有使用spring框架。为什么我的cacheManager
为空,但是通过API调用时可以轻松删除:
http://localhost:8080/myresource/clearCache,我的缓存很容易清除。
cache is being cleared........
11:19:31,154 INFO [org.ehcache.core.EhcacheManager] (default task-8) Cache 'cacheOfmap' removed from EhcacheManager.
答案 0 :(得分:1)
在调用clearAllCache
方法之前,您创建了new CacheHelper()
。因此,永远不会初始化此实例的cacheManager
属性(只能在putInCacheFromDb
方法中对其进行初始化)。
我猜想当您通过API调用它时,您有一个bean /单个实例被调用以填充缓存,然后再也不会销毁。因此必须使用此实例。
EDIT :回答为什么在构造函数中初始化cacheManager
的问题。
您当前的代码运行如下:
// 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();