3

I'm trying to add caching to a springboot application and I am running into an issue where a org.ehcache.jsr107.MultiCacheException exception is being thrown during startup.

I am using the following ( all loaded via Maven pom file): Springboot 1.5.5, Ehcache 3.3.1, Javax cache 1.0.0

My SpringBootApplication looks like this:

@SpringBootApplication
@EnableCaching
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

I have a CacheConfig class that contains the following:

@Component
public class CacheConfig implements JCacheManagerCustomizer{
    @Override
    public void customize(javax.cache.CacheManager cacheManager) {
        cacheManager.createCache("item", new MutableConfiguration<>()
                .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 5)))
                .setStoreByValue(false)
                .setStatisticsEnabled(true));
    }
}

And my ehcache.xml file contains:

<config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>

    <service>
        <jsr107:defaults>
            <jsr107:cache name="item" template="heap-cache"/>
        </jsr107:defaults>
    </service>

    <cache-template name="heap-cache">
        <listeners>
            <listener>
                <class>org.terracotta.ehcache.EventLogger</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>UPDATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
                <events-to-fire-on>REMOVED</events-to-fire-on>
                <events-to-fire-on>EVICTED</events-to-fire-on>
            </listener>
        </listeners>
        <resources>
            <heap unit="entries">2000</heap>
            <offheap unit="MB">100</offheap>
        </resources>
    </cache-template>
</config>

The test item service contains:

@Service
public class ItemService {

    @CacheResult(cacheName = "item")
    public String getItem(int itemNumber) {
        switch (itemNumber) {
            case 1:
                return "Item 1";
            case 2:
                return "Item 2";
            default:
                return "No Item";

        }
    }
}

And finally, the application.properties contains:

spring.cache.jcache.config=classpath:ehcache.xml

When I run the application, I get the following exceptions ending with:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jCacheCacheManager' defined in class path resource [org/springframework/boot/autoconfigure/cache/JCacheCacheConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.cache.CacheManager]: Factory method 'jCacheCacheManager' threw exception; nested exception is org.ehcache.jsr107.MultiCacheException: [Exception 0] org.terracotta.ehcache.EventLogger
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    ... 70 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.cache.CacheManager]: Factory method 'jCacheCacheManager' threw exception; nested exception is org.ehcache.jsr107.MultiCacheException: [Exception 0] org.terracotta.ehcache.EventLogger
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    ... 83 common frames omitted
Caused by: org.ehcache.jsr107.MultiCacheException: [Exception 0] org.terracotta.ehcache.EventLogger
    at org.ehcache.jsr107.ConfigurationMerger.mergeConfigurations(ConfigurationMerger.java:138) ~[ehcache-3.3.1.jar:3.3.1 01f4b2121ef38b7e7d95c952c773881d5b1051d8]
    at org.ehcache.jsr107.Eh107CacheManager.createCache(Eh107CacheManager.java:190) ~[ehcache-3.3.1.jar:3.3.1 01f4b2121ef38b7e7d95c952c773881d5b1051d8]
    at com.example.cacheexample.CacheConfig.customize(CacheConfig.java:18) ~[classes/:na]
    at org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration.customize(JCacheCacheConfiguration.java:149) ~[spring-boot-autoconfigure-1.5.5.RELEASE.jar:1.5.5.RELEASE]
    at org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration.jCacheCacheManager(JCacheCacheConfiguration.java:104) ~[spring-boot-autoconfigure-1.5.5.RELEASE.jar:1.5.5.RELEASE]
    at org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration$$EnhancerBySpringCGLIB$$e218d7d3.CGLIB$jCacheCacheManager$1(<generated>) ~[spring-boot-autoconfigure-1.5.5.RELEASE.jar:1.5.5.RELEASE]
    at org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration$$EnhancerBySpringCGLIB$$e218d7d3$$FastClassBySpringCGLIB$$b2f1636b.invoke(<generated>) ~[spring-boot-autoconfigure-1.5.5.RELEASE.jar:1.5.5.RELEASE]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) ~[spring-context-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration$$EnhancerBySpringCGLIB$$e218d7d3.jCacheCacheManager(<generated>) ~[spring-boot-autoconfigure-1.5.5.RELEASE.jar:1.5.5.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    ... 84 common frames omitted

I'm not certain where to go with this as I pretty much replicated what was found on this site: http://www.ehcache.org/blog/2016/05/18/ehcache3_jsr107_spring.html

Any insight would be very appreciated.

Thanks.

Brad
  • 121
  • 1
  • 5
  • How does your service annotated with `@CacheResult` looks like? Add it to the question. – Mateusz Chrzaszcz Jul 26 '17 at 23:12
  • Okay, I've added what the test service looks like. – Brad Jul 26 '17 at 23:51
  • Have a look at the sources - - try to put a breakpoint to figure out what is happening in createCache method in https://github.com/ehcache/ehcache3/blob/master/107/src/main/java/org/ehcache/jsr107/Eh107CacheManager.java – Mateusz Chrzaszcz Jul 27 '17 at 00:04
  • Okay, that was the ticket. Turns out that the org.terracotta.ehcache.EventLogger class as defined in the ehcache.xml file is not actually included in ehcache distribution. A NoClassDefFoundError exception was being generated, and resulted in the MultiCacheException being thrown. I created my own EventLogger and everything is working as expected now. Thanks for pointing me in the right direction. – Brad Jul 27 '17 at 02:04
  • good to hear that. Please do add your own answer to your question and accept it so people will know what they can refer to :) – Mateusz Chrzaszcz Jul 27 '17 at 17:49
  • 1
    Also feel free to file this on https://github.com/ehcache/ehcache3/issues as an issue as the exception message is really not helpful. – Louis Jacomet Jul 27 '17 at 20:19
  • @LouisJacomet not just unhelpful but actually misleading. – Mateusz Chrzaszcz Jul 27 '17 at 22:45
  • How is it misleading? It listed the problematic type but missed the exception type that would have indicated what made the type special. – Louis Jacomet Jul 28 '17 at 12:27
  • I am getting the same exception, but in unit test cases, any idea how to handle this? org.ehcache.jsr107.MultiCacheException: [Exception 0] Cache 'transaction' already exists – Niraj Sonawane Aug 30 '18 at 03:38

1 Answers1

7

Turns out that the org.terracotta.ehcache.EventLogger class as defined in the ehcache.xml file was just an example logger for the purpose of the test program defined in blog post above. The package name lead me to believe it was a part of the ehcache distribution.

When I stepped through the code, I saw a NoClassDefFoundError exception was being generated, and resulted in the MultiCacheException being thrown. Nothing in the stack track made it clear that a NoClassDefFoundError was the real culprit. I created my own EventLogger and everything is working as expected now.

Thanks for the pointers!

Brad
  • 121
  • 1
  • 5
  • An example implementation of the missing class can be found here https://github.com/gibsong/ehcache-jsr107-spring/blob/master/src/main/java/org/terracotta/ehcache/EventLogger.java – Luc De pauw Aug 16 '18 at 08:10