C Taylor
C Taylor

Reputation: 149

Unable to create CacheManager bean

I am having trouble creating a Spring CacheManager. When I try to boot up, I get the an error creating bean message.

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@EnableCaching
@Configuration
public class CacheConfig {

  @Bean
  public CacheManager cacheManager() {
    log.trace("Creating cache manager.");
    return new ConcurrentMapCacheManager("myCache");
  }
}

I've put a debug marker on the log line, but I don't reach it. Something seems to be happening before we even get to the method.

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
    at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:350)
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [org/chuck/config/CacheConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cache.CacheManager]: Illegal arguments to factory method 'cacheManager'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class

Solution (thanks to Nigel Savage)

Don't name the class CacheConfig

Upvotes: 1

Views: 14844

Answers (2)

Pablo Perez
Pablo Perez

Reputation: 1

For any reason SpringBoot doesn't load the CacheManager from the ehcache library so a solution is to create the specific bean CacheManager into your project. You can follow the same way as Baeldung page.

https://github.com/eugenp/tutorials/blob/master/spring-boot-modules/spring-boot-caching/src/main/java/com/baeldung/caching/config/CachingConfig.java

https://www.baeldung.com/spring-boot-ehcache

this is a sample :

package com.cache.ehcache.config;

import java.util.Arrays;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
@ComponentScan("com.cache.ehcache.service")
public class CacheConfig {
    @Bean
    public CacheManager cacheManager() {
        final SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("directory"), new ConcurrentMapCache("addresses")));
        return cacheManager;
    }

This works to me.

Upvotes: 0

user1409784
user1409784

Reputation:

For the spring class/bean scan, the namespace has a bunch of cache annotations[1].
Here they are creating their own config bean/class for caching CacheConfig, which is a typical name to use and has the classname CacheConfig.

The issue here is that the Spring developers have an annotation[1] @CacheConfig which also has a class name CacheConfig.

From the error it appears that the Spring CDI context is attempting to proxy[2] the org.chuck.config.CacheConfig.class via a BeanFactory for the org.springframework.cache.CacheManager class which has factory methods that reference the org.springframework.cache.annotation.CacheConfig class(in this case an interface)

I think this could only happen if the factory is not using the fully qualified class name, the only evidence I could quickly find for this is a comment from this issue[3]

simple solution is just to rename their own config bean/class

[1] https://spring.io/guides/gs/caching/
[2] you should learn how CDI uses proxy classes and scope heuristics to create objects, the proxy is a subclass of the bean that is created at run-time, we can get a hint for this in the error message object is not an instance of declaring class
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
[3] https://github.com/spring-projects/spring-framework/issues/19229
"You could of course specify a custom BeanNameGenerator for your scan and use more unique bean names, e.g. the fully-qualified class name."

Upvotes: 2

Related Questions