3

We need to implement several methods that have different caching times. Each method is annotated with @Cacheable and our current solution includes multiple CacheManager that are set in a CachingConfigurerSupport.

public class CachingConfiguration extends CachingConfigurerSupport {

  @Override
  @Bean
  public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.DAYS));
    return cacheManager;
  }

  @Bean
  public CacheManager anotherCache() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES));
    return cacheManager;
  }
}

The @Cacheable annotation then included the cacheManager: @Cacheable(cacheNames = "someCache", cacheManager = "anotherCache")

Basically that's fine but is also errorprune if you forget the cacheManager parameter etc.

So I currently try to find a better solution but as far as I can see, there is currently no general accepted way to go.

Imho the main advantage of the CaffeineCacheManager compared to e.g. SimpleCacheManager is the possibility to define a base configuration and then initialize additional caches lazily. But wouldn't it be great if you are able to set additional caches which are never reinitialized?

Those caches must be used preferentially and created in the CachingConfigurerSupport.

Maybe I'm missing something, but shouldn't this solve the problem that has already been discussed in several threads in different forms?

deveth0
  • 488
  • 1
  • 5
  • 15
  • You might want to chime in on this [pull request](https://github.com/spring-projects/spring-framework/pull/1506). The integration was a direct port of the prior Guava version. – Ben Manes Aug 17 '18 at 14:44
  • Also see this [answer](https://github.com/spring-projects/spring-boot/issues/7235#issuecomment-256587531) - “expose individual caches as @Beans and Spring Boot will automatically detect that and create a CacheManager for you” – Ben Manes Aug 17 '18 at 14:49
  • Thanks @Ben I hoped that you would find this question ;) exposing individual caches as Beans is OK but not really configurable. I'll try to help in the PR if possible – deveth0 Aug 17 '18 at 18:38
  • 1
    New PR created https://github.com/spring-projects/spring-framework/pull/1932 – deveth0 Aug 18 '18 at 13:46

2 Answers2

2

Recently I decided to turn my initial PR into a separate tiny project.

To start using it just add the latest dependency from Maven Central:

<dependency>
    <groupId>io.github.stepio.coffee-boots</groupId>
    <artifactId>coffee-boots</artifactId>
    <version>2.0.0</version>
</dependency>

Format of properties is the following:

coffee-boots.cache.spec.myCache=maximumSize=100000,expireAfterWrite=1m

If no specific configuration is defined, CacheManager defaults to Spring's behavior.

stepio
  • 865
  • 2
  • 9
  • 22
0

Simple way without any thrid-party lib:

spring.cache.type=caffeine
# default spec (optional)
spring.cache.caffeine.spec=maximumSize=250,expireAfterWrite=15m
# specific specs (also optional)
caffeine.specs.places=maximumSize=1000,expireAfterWrite=1h

Register custom caches:

applicationContext.registerBean { context ->
    CacheManagerCustomizer<CaffeineCacheManager> { cacheManager ->
        for (spec in Binder.get(context.environment).bindOrCreate("caffeine.specs", HashMap::class.java)) {
            cacheManager.registerCustomCache(spec.key.toString(), Caffeine.from(spec.value.toString()).build())
        }
    }
}
Vladimir Konkov
  • 161
  • 2
  • 9