I create a spring boot project use jcache, config like this:
spring.cache.jcache.provider=org.ehcache.jsr107.EhcacheCachingProvider
spring.cache.jcache.config=classpath:ehcache.xml
I want to create cache dynamically, my code like this:
@Autowired
lateinit var cacheManager: CacheManager;
@RequestMapping("setCache")
fun setCache(key: String, v: String) {
cacheManager.getCache("test").put(key, v)
}
@RequestMapping("getCache")
fun getCache(key: String) {
val v = cacheManager.getCache("test")[key]
println(v)
}
but I can't get cache when cache doesn't exist, I want to create cache dynamically.
I came around the same issue. There are basically two options.
CacheResolver in the @Cacheable annotationimport 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(...){
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With