I came around the same issue. There are basically two options.
- Either you create and wrap the CacheManager during the CacheManager creation in your Spring Boot Cache Configuration
- OR You use an own implementation of an
CacheResolver
in the @Cacheable
annotation
import javax.cache.CacheManager;
import javax.cache.spi.CachingProvider;
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public CacheManager extendedCacheManager() {
CachingProvider provider = Caching.getCachingProvider();
// get the cache manager according your provider you have chosen
CacheManager cacheManager = provider.getCacheManager(...);
// wrap it with your own implementation
return new MyCacheManager(cacheManager);
}
}
Own CacheManager Wrapper
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.configuration.Configuration;
import javax.cache.configuration.MutableConfiguration;
public class MyCacheManager implements CacheManager {
CacheManager cacheManager;
public MyCacheManager(CacheManager cacheManager) {
super();
this.cacheManager = cacheManager;
}
...
public <K, V> Cache<K, V> getCache(String cacheName, Class<K> keyType, Class<V> valueType) {
Cache<K, V> cache = cacheManager.getCache(cacheName, keyType, valueType);
if (cache == null) {
MutableConfiguration<K, V> configuration = new MutableConfiguration<>();
cache = this.cacheManager.createCache(cacheName, configuration);
}
return cache;
}
}
For to the other possibility via CacheResolver
. First you need an own implementation of the interface javax.cache.annotation.CacheResolver
and javax.cache.annotation.CacheResolverFactory
. you can do this in the same class or having separate classes.
import javax.cache.annotation.CacheResolver;
import javax.cache.annotation.CacheResolverFactory;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.configuration.MutableConfiguration;
public class AutoCacheResolverFactory implements CacheResolverFactory, CacheResolver {
CacheManager cacheManager;
public AutoCacheResolverFactory(CacheManager cacheManager) {
super();
this.cacheManager = cacheManager;
}
// from interface CacheResolverFactory
@Override
public CacheResolver getCacheResolver(CacheMethodDetails<? extends Annotation> cacheMethodDetails) {
return this;
}
@Override
public CacheResolver getExceptionCacheResolver(CacheMethodDetails<CacheResult> cacheMethodDetails) {
return this;
}
// from interface CacheResolver
public <K, V> javax.cache.Cache<K, V> resolveCache(CacheInvocationContext<?> cacheInvocationContext) {
String cacheName = cacheInvocationContext.getCacheName();
javax.cache.Cache<K, V> cache = cacheManager.getCache(cacheName);
if (cache == null) {
MutableConfiguration<K, V> configuration = new MutableConfiguration<>();
cache = this.cacheManager.createCache(cacheName, configuration);
}
return cache;
}
}
and then at your method where you like to cache the results use the annotation accordingly.
import javax.cache.annotation.CacheResult;
public class MyService {
...
@CacheResult(cacheResolverFactory= AutoCacheResolverFactory.class)
public List<MyExpensiveResult> getExpensiveResult(...){
...
}
}