Spring Boot application startup fails when an existing cache exists (e.g. EhCache) #1024

Open
mraible opened this Issue Oct 7, 2016 · 11 comments

Comments

Projects
None yet
3 participants
@mraible
Contributor

mraible commented Oct 7, 2016

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 mraible/jhipster-stormpath-example#2 for more information.

@lhazlewood

This comment has been minimized.

Show comment
Hide comment
@lhazlewood

lhazlewood Oct 7, 2016

Member

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?

Member

lhazlewood commented Oct 7, 2016

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?

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Oct 7, 2016

Contributor

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!

Contributor

mraible commented Oct 7, 2016

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!

@lhazlewood

This comment has been minimized.

Show comment
Hide comment
@lhazlewood

lhazlewood Oct 7, 2016

Member

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.

Member

lhazlewood commented Oct 7, 2016

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.

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Oct 7, 2016

Contributor

The ehcache.xml generated by JHipster seems to have a defaultCache.

Contributor

mraible commented Oct 7, 2016

The ehcache.xml generated by JHipster seems to have a defaultCache.

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Oct 10, 2016

Contributor

@lhazlewood Here's how to reproduce this issue in examples/spring-boot-webmvc-angular:

  1. 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>
  2. Add an ehcache.xml file to src/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>
  3. 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;
        }
    }
  4. Start the app and watch it blow up.

Contributor

mraible commented Oct 10, 2016

@lhazlewood Here's how to reproduce this issue in examples/spring-boot-webmvc-angular:

  1. 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>
  2. Add an ehcache.xml file to src/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>
  3. 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;
        }
    }
  4. Start the app and watch it blow up.

@mraible mraible referenced this issue in jhipster/generator-jhipster Oct 17, 2016

Closed

Improvement for Cache #4333

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Oct 20, 2016

Contributor

FYI: I tried generating a JHipster application with Hazelcast instead of EhCache and everything works w/o additional configuration.

Contributor

mraible commented Oct 20, 2016

FYI: I tried generating a JHipster application with Hazelcast instead of EhCache and everything works w/o additional configuration.

@mraible mraible referenced this issue in jhipster/generator-jhipster Nov 1, 2016

Closed

Upgrade to Hibernate 5.2 and Ehcache 3 #4195

@henri-tremblay

This comment has been minimized.

Show comment
Hide comment
@henri-tremblay

henri-tremblay Nov 1, 2016

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

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

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Nov 1, 2016

Contributor

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)
Contributor

mraible commented Nov 1, 2016

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)
@henri-tremblay

This comment has been minimized.

Show comment
Hide comment
@henri-tremblay

henri-tremblay Nov 1, 2016

I'm just not sure about something. Are you using Ehcache3 and JSR107?

I'm just not sure about something. Are you using Ehcache3 and JSR107?

@mraible

This comment has been minimized.

Show comment
Hide comment
@mraible

mraible Nov 1, 2016

Contributor

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.

Contributor

mraible commented Nov 1, 2016

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.

@henri-tremblay

This comment has been minimized.

Show comment
Hide comment
@henri-tremblay

henri-tremblay Nov 1, 2016

Please do. I meant: "Is stormpath ready to use Ehcache 3 or JCache?"

On 1 November 2016 at 17:30, Matt Raible notifications@github.com 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
#1024 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABKRM3ItQDYEklWtkJlP7ruzi7x3mKh-ks5q569sgaJpZM4KRWQj
.

Please do. I meant: "Is stormpath ready to use Ehcache 3 or JCache?"

On 1 November 2016 at 17:30, Matt Raible notifications@github.com 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
#1024 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABKRM3ItQDYEklWtkJlP7ruzi7x3mKh-ks5q569sgaJpZM4KRWQj
.

@mraible mraible referenced this issue in ehcache/ehcache3-samples Nov 2, 2016

Closed

JHipster fails to auto-create caches when using EhCache #11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment