stormpath-sdk-java
stormpath-sdk-java copied to clipboard
Spring Boot application startup fails when an existing cache exists (e.g. EhCache)
When an existing cache configuration exists and Stormpath caches are not configured, startup fails with:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stormpathApplication' defined in class path resource [com/stormpath/spring/boot/autoconfigure/StormpathAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.stormpath.sdk.application.Application]: Factory method 'stormpathApplication' threw exception; nested exception is java.lang.IllegalArgumentException: spring cache instance cannot be null.
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1128)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1023)
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:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 35 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.stormpath.sdk.application.Application]: Factory method 'stormpathApplication' threw exception; nested exception is java.lang.IllegalArgumentException: spring cache instance cannot be null.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 47 common frames omitted
Caused by: java.lang.IllegalArgumentException: spring cache instance cannot be null.
at com.stormpath.sdk.lang.Assert.notNull(Assert.java:80)
at com.stormpath.spring.cache.SpringCache.<init>(SpringCache.java:38)
at com.stormpath.spring.cache.SpringCacheManager.getCache(SpringCacheManager.java:72)
At the very least, we should print the name of the cache that's missing so users can add this to their existing cache configuration. See https://github.com/mraible/jhipster-stormpath-example/issues/2 for more information.
I'm confused - Spring's CacheManager, if one exists, will lazily create caches by name automatically - there is no need to define/pre-configure cache objects within the cache manager.
If no Spring CacheManager exists, we should default to the DisabledCacheManager
.
2 separate issues, no?
Maybe Spring's default cache manager does this, but JHipster uses EhCache and EhCacheCacheManager appears to be the CacheManager in play. It doesn't seem to create caches by name automatically. See the example app's CacheConfiguration.java to see how it's configured. If there's a way to configure it so it auto-creates caches, great!
Ehcache supports this automatically - it's called a defaultCache
. It sounds like JHipster should probably want to ensure that's enabled? Most EHCache users I've seen have it enabled because it's often painful without it.
http://www.ehcache.org/documentation/2.8/configuration/configuration.html
While a defaultCache configuration is not required, an error is generated if caches are created by name (programmatically) with no defaultCache loaded.
The ehcache.xml generated by JHipster seems to have a defaultCache.
@lhazlewood Here's how to reproduce this issue in examples/spring-boot-webmvc-angular:
-
Add dependencies for Spring Boot's caching autoconfiguration and EhCache:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.10</version> </dependency>
-
Add an
ehcache.xml
file tosrc/main/resources
:<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" name="CM1" updateCheck="false" maxBytesLocalHeap="16M"> <diskStore path="java.io.tmpdir"/> <defaultCache eternal="false" overflowToDisk="false" /> </ehcache>
-
Add a
CacheConfiguration.java
class that configures EhCache:package com.stormpath.spring.boot.examples; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PreDestroy; @Configuration @EnableCaching public class CacheConfiguration { private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class); private net.sf.ehcache.CacheManager cacheManager; @PreDestroy public void destroy() { cacheManager.shutdown(); } @Bean public CacheManager cacheManager() { log.debug("Starting Ehcache"); cacheManager = net.sf.ehcache.CacheManager.create(); cacheManager.getConfiguration().setMaxBytesLocalHeap("16M"); EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(); ehCacheManager.setCacheManager(cacheManager); return ehCacheManager; } }
-
Start the app and watch it blow up.
FYI: I tried generating a JHipster application with Hazelcast instead of EhCache and everything works w/o additional configuration.
To get auto creation, you can do this
<?xml version="1.0" encoding="UTF-8"?>
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
xsi:schemaLocation="
http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
<service>
<jsr107:defaults default-template="simple"/>
</service>
<cache-template name="simple">
<expiry>
<ttl unit="seconds">3600</ttl>
</expiry>
<heap>100</heap>
</cache-template>
</config>
More details in Ehcache documentation
Thanks for the tip @henri-tremblay! I tried this ehcache.xml
config in your JHipster fullstack sample (after integrating Stormpath). Unfortunately, it doesn't work. Not sure if this is a Stormpath issue or caused by EhCache.
Caused by: java.lang.IllegalArgumentException: spring cache instance cannot be null.
at com.stormpath.sdk.lang.Assert.notNull(Assert.java:80)
at com.stormpath.spring.cache.SpringCache.<init>(SpringCache.java:38)
at com.stormpath.spring.cache.SpringCacheManager.getCache(SpringCacheManager.java:72)
at com.stormpath.sdk.impl.ds.cache.DefaultCacheResolver.getCache(DefaultCacheResolver.java:40)
at com.stormpath.sdk.impl.ds.cache.AbstractCacheFilter.getCache(AbstractCacheFilter.java:74)
at com.stormpath.sdk.impl.ds.cache.AbstractCacheFilter.getCachedValue(AbstractCacheFilter.java:48)
at com.stormpath.sdk.impl.ds.cache.ReadCacheFilter.getCachedResourceData(ReadCacheFilter.java:91)
at com.stormpath.sdk.impl.ds.cache.ReadCacheFilter.filter(ReadCacheFilter.java:55)
at com.stormpath.sdk.impl.ds.DefaultFilterChain.filter(DefaultFilterChain.java:52)
at com.stormpath.sdk.impl.ds.api.DecryptApiKeySecretFilter.filter(DecryptApiKeySecretFilter.java:63)
at com.stormpath.sdk.impl.ds.DefaultFilterChain.filter(DefaultFilterChain.java:52)
at com.stormpath.sdk.impl.ds.EnlistmentFilter.filter(EnlistmentFilter.java:42)
at com.stormpath.sdk.impl.ds.DefaultFilterChain.filter(DefaultFilterChain.java:52)
at com.stormpath.sdk.impl.ds.DefaultDataStore.getResourceData(DefaultDataStore.java:330)
at com.stormpath.sdk.impl.ds.DefaultDataStore.getResource(DefaultDataStore.java:245)
at com.stormpath.sdk.impl.ds.DefaultDataStore.getResource(DefaultDataStore.java:233)
at com.stormpath.sdk.impl.client.DefaultClient.getCurrentTenant(DefaultClient.java:103)
at com.stormpath.sdk.impl.client.DefaultClient.getApplications(DefaultClient.java:220)
at com.stormpath.spring.config.AbstractStormpathConfiguration.stormpathApplication(AbstractStormpathConfiguration.java:134)
at com.stormpath.spring.boot.autoconfigure.StormpathAutoConfiguration.stormpathApplication(StormpathAutoConfiguration.java:44)
at com.stormpath.spring.boot.autoconfigure.StormpathAutoConfiguration$$EnhancerBySpringCGLIB$$1a69bbf2.CGLIB$stormpathApplication$1(<generated>)
at com.stormpath.spring.boot.autoconfigure.StormpathAutoConfiguration$$EnhancerBySpringCGLIB$$1a69bbf2$$FastClassBySpringCGLIB$$ac7a5be0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at com.stormpath.spring.boot.autoconfigure.StormpathAutoConfiguration$$EnhancerBySpringCGLIB$$1a69bbf2.stormpathApplication(<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)
I'm just not sure about something. Are you using Ehcache3 and JSR107?
Yes, because I'm producing this problem in the fullstack example you posted. I can create a branch with PR to show the problem if you like.
Please do. I meant: "Is stormpath ready to use Ehcache 3 or JCache?"
On 1 November 2016 at 17:30, Matt Raible [email protected] wrote:
Yes, because I'm producing this problem in the fullstack example you posted. I can create a branch with PR to show the problem if you like.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/stormpath/stormpath-sdk-java/issues/1024#issuecomment-257704312, or mute the thread https://github.com/notifications/unsubscribe-auth/ABKRM3ItQDYEklWtkJlP7ruzi7x3mKh-ks5q569sgaJpZM4KRWQj .