2016-01-15 13 views
5

Ich habe ein Problem beim Einrichten eines jcache mit spring cache abstraction.Wie erstelle ich eine Jcache in Spring Java config?

@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; 
    } 

} 

Ich benutze Caffein als Jcache. Ich kann einfach nicht verstehen, was ich falsch mache. Würdest du erklären, wie es richtig gemacht wird?

Was ich erhalte ist NPE in Zeile 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

Vielen Dank für Ihre Rückmeldung! In der nächsten Version '2.1.0' wird die' CaffeineConfiguration' den 'store-by-value' deaktivieren und den Kopierer bei der Konstruktion auf' JavaSerializationCopier' setzen (falls store-by-value aktiviert ist und kein Kopierer explizit gesetzt ist). Dies sollte eine freundlichere Grundeinstellung sein, damit andere Benutzer nicht von dieser Ausnahme überrascht werden. –

Antwort

3

mehr über Caffeine Konfiguration lesen. Sein JCache Adapter verwendet Standardspezifikation (JCache) Einstellungen, die besagt, dass Einträge nie ablaufen und nach Wert gespeichert werden (kopiert, wenn put/aus dem Cache abgerufen). (reference here).

Wenn der Cache auf das Kopieren von Instanzen eingestellt ist, sollten Sie eine geeignete Copier auswählen, die das übernimmt. So können Sie einfach schreiben:

caffeineConfiguration.setCopierFactory(JavaSerializationCopier::new); 

oder

caffeineConfiguration.setCopierFactory(Copier::identity); 

Es hängt davon ab, ob Sie im Falle eines Cache-Schlüssel/Wert-Mutationen, sicher sein möchten.

Dennoch die empfohlene Option istdefault settings zu verwenden, wo store-by-value Option deaktiviert ist und Kopierer ist notwendig:

Config config = ConfigFactory.load(); 
CaffeineConfiguration<String, List<Product>> caffeineConfiguration = TypesafeConfigurator.defaults(config); 
caffeineConfiguration.setExpiryPolicyFactory(factoryOf(new AccessedExpiryPolicy(new Duration(
      TimeUnit.MINUTES, 60)))); 

Alternativ können Sie nur store-by-value Einstellung deaktivieren:

caffeineConfiguration.setStoreByValue(false); 
+0

ja, löste mein Problem. Danke für die Erklärung! – marknorkin

+1

@Mark JCache ist manchmal ziemlich komisch. Alternativ ist die Verwendung der Guava-Adapter plus Spring Cache-Integration eine leichtere, besser vorhersagbare Beilage. Wenn die Koffein-Unterstützung der nächsten Version von Spring hinzugefügt wird, kann diese Problemumgehung entfernt werden. Wenn Sie also JCache-APIs nicht verwenden, empfehle ich Benutzern, dies zu vermeiden. Das JSR107 TCK ist nicht übermäßig robust, also verbessert das Verbessern der Tests und der Fehlermeldung des Adapters auf meiner To-do-Liste. –

+0

@BenManes yeap, es gibt eine gebundene jcache api. Wir benutzen auch Frühling 4.2.4 und warten auf ein 4.4, damit Koffeinunterstützung drin ist. trotzdem danke für einen Hinweis :) – marknorkin

Verwandte Themen