I have a method as following:
@Cacheable(value = "SAMPLE")
public List<SomeObj> find() {
// Method that initiates and returns the List<SomeObj> and takes around 2-3 seconds, does some logging too
}
And I am enabling caching in one of my configuration classes:
@EnableCaching
@Configuration
public SomeConf extends CachingConfigurerSupport {
// Here I also initialize my classes with @Cacheable annotation
@Bean
@Override
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Collections.singletonList((new ConcurrentMapCache("SAMPLE"))));
return cacheManager;
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver(cacheManager());
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
}
I have the following in my pom.xml
:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>1.5.14.RELEASE</version>
</dependency>
I am declaring a CacheManager
as follows:
@Bean
public CacheManager cacheManager(){
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Collections.singletonList((new ConcurrentMapCache("SAMPLE"))));
return cacheManager;
}
When I get an @Autowired
CacheManager
instance into one of my @Service
s I can see that there exists a cache with name "SAMPLE"
, but its entries are always empty. I call again and again the method find()
, but it doesn't seem to populate the cache.
I have tried to put an argument (say int a
) to the find()
method and put it as key = "#a"
to @Cacheable
, but nothing changed.
When I try to recreate the issue in an isolated environment, I can see that it works properly. But when I add my dependencies (non open-source company libraries, which include an EhCache
configuration as well) it doesn't work. How can I debug this, what am I doing wrong?
Update:
I have also tried to use cacheManager = myCacheManager
in @Cacheable
as well. No luck.
Update 2:
I am using AspectJ
and Spring AOP. I think that it may have something to do with it. I have tried @EnableCaching(mode = AdviceMode.ASPECTJ)
with @EnableLoadTimeWeaving
but same thing.
Update 3:
I was finally able to reproduce the issue, here it is: client-api-cache
Basically when you run the application and telnet localhost 9000
after you send any line to it, it should print NOT CACHED
once even though the method is called twice in CachedController
(Second coming from the cache). But it prints twice.
As Andrews S noted, this does sound like colliding caches in the auto configuration.
@EnableCaching
's javadoc has some useful notes regarding how thecacheManager
is selected and, specifically, an idea on how to proceed. What you'd do in this case is establish aCachingConfigurer
to select your cache - perhaps you can just extendCachingConfigurerSupport
(as in example below) and be done.You may also find this thread useful: How to have multiple cache manager configuration in spring cache java
Edit:
So thankfully I have a project using caching and wrote this little bit:
Aside from seeing my established cache names pop out, I do note that context is outputting:
The
context.getClass()
output is of interest, given your Aspect question. That said I have a very similar logging/timing aspect in my own code that isn't causing any confusion for the rest of the caching. Try my resolver out and see if the output is instructive on what calls are being made against the cache code.Edit #2:
The TLDR issue appears to be that we're expecting
@Cacheable
to work in places where it can't - mainly due to the fact that the framework hasn't fully brought itself up yet. You are usingInitializingBean
and I tried replacing that functionality with@PostConstruct
which both fail.Spring cache using @Cacheable during @PostConstruct does not work
I got your github code. I initially ran into the blocking issue you reported in the other thread but, in the interest of pursuing one thing at a time, I just commented out that blocking code and called
service.cachedMethod()
directly.I ran your jar file with --trace and noted that the cacheManager was scanned and created, but it wasn't initially obvious to me when it was being invoked. So, no big deal, I just had the bean method throw a
RuntimeException
. Upon doing that I noted that both yourNOT CACHED
lines print prior to that invocation - another hint that things aren't set up as expected.Finally, I added
System.out.println(service.toString());
in your Controller's afterPropertiesSet() method and sawcom.company.client.api.domain.CachedServiceImpl@2bbfb8b
- your object, not a proxied object. Thus no caching.So, in general, you'll need to rework how you're trying to enable this functionality.
Make sure you are setting your cache into cachemanager as below.
The root cause is that you are misusing "afterPropertiesSet". So, what you are doing is endless loop and never pass control back to the Spring pipeline, so Spring isn't able to init caching facility properly.
Check out code which fixes our problem: https://dumpz.org/cbx8h28KeAss