问题
I have a problem setting up a jcache with spring cache abstraction.
@Configuration
@EnableCaching
public class CacheConfig {
@Bean(name = "caffeineCachingProvider")
public CachingProvider caffeineCachingProvider() {
return new CaffeineCachingProvider();
}
@Bean(name = "caffeineCacheManager")
public JCacheCacheManager getSpringCacheManager() {
CacheManager cacheManager = caffeineCachingProvider().getCacheManager();
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = new CaffeineConfiguration<>();
caffeineConfiguration.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 60))));
Cache<String, List<Product>> productCache = cacheManager.createCache("productCache", caffeineConfiguration);
JCacheCacheManager jCacheCacheManager = new JCacheCacheManager(cacheManager);
return jCacheCacheManager;
}
}
I'm using Caffein as Jcache. I just cannot understand what i'm doing wrong. Would you explain how to do it properly?
What i'm getting is NPE
at line cacheManager.createCache(...)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'caffeineCacheManager' defined in com.myapp.spring.config.CacheConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.jcache.JCacheCacheManager]: Factory method 'getSpringCacheManager' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:677)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1912)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.jcache.JCacheCacheManager]: Factory method 'getSpringCacheManager' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 34 more
Caused by: java.lang.NullPointerException
at com.github.benmanes.caffeine.jcache.CacheProxy.<init>(CacheProxy.java:109)
at com.github.benmanes.caffeine.jcache.CacheFactory$Builder.newCacheProxy(CacheFactory.java:160)
at com.github.benmanes.caffeine.jcache.CacheFactory$Builder.build(CacheFactory.java:145)
at com.github.benmanes.caffeine.jcache.CacheFactory.createCache(CacheFactory.java:82)
at com.github.benmanes.caffeine.jcache.CacheManagerImpl.lambda$createCache$0(CacheManagerImpl.java:98)
at com.github.benmanes.caffeine.jcache.CacheManagerImpl$$Lambda$23/388708304.apply(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
at com.github.benmanes.caffeine.jcache.CacheManagerImpl.createCache(CacheManagerImpl.java:94)
at com.myapp.spring.config.CacheConfig.getSpringCacheManager(CacheConfig.java:55)
at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611.CGLIB$getSpringCacheManager$1(<generated>)
at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611$$FastClassBySpringCGLIB$$b70e5f67.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:355)
at com.myapp.spring.config.CacheConfig$$EnhancerBySpringCGLIB$$4f46e611.getSpringCacheManager(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 35 more
回答1:
Read more about Caffeine
configuration. Its JCache
adapter uses default specification (JCache
) settings which states that entries never expires and are stored by value (copied when put/retrieved from cache). (reference here).
When cache is set to copying instances, you should choose adequate Copier
which will handle that. So you can just write:
caffeineConfiguration.setCopierFactory(JavaSerializationCopier::new);
or
caffeineConfiguration.setCopierFactory(Copier::identity);
It depends on if you want to be safe in case of cache key/value mutations.
Nevertheless, the recommended option is to use default settings where store-by-value
option is disabled and copier is necessary:
Config config = ConfigFactory.load();
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = TypesafeConfigurator.defaults(config);
caffeineConfiguration.setExpiryPolicyFactory(factoryOf(new AccessedExpiryPolicy(new Duration(
TimeUnit.MINUTES, 60))));
Alternatively, you can just disable store-by-value
setting by:
caffeineConfiguration.setStoreByValue(false);
来源:https://stackoverflow.com/questions/34809817/how-to-create-a-jcache-in-spring-java-config