55

I have implemented a cache and now I want to add an expiry time.

How can I set an expiry time in spring boot with @Cacheable?

This is a code snippet:

@Cacheable(value="forecast",unless="#result == null")
risingTide
  • 1,754
  • 7
  • 31
  • 60
nole
  • 1,422
  • 4
  • 20
  • 32

8 Answers8

36

I use life hacking like this:

@Configuration
@EnableCaching
@EnableScheduling
public class CachingConfig {

  public static final String GAMES = "GAMES";

  @Bean
  public CacheManager cacheManager() {
    ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(GAMES);
    return cacheManager;
  }

  @CacheEvict(allEntries = true, value = {GAMES})
  @Scheduled(fixedDelay = 10 * 60 * 1000 ,  initialDelay = 500)
  public void reportCacheEvict() {
    System.out.println("Flush Cache " + dateFormat.format(new Date()));
  }

}
ℛɑƒæĿᴿᴹᴿ
  • 4,983
  • 4
  • 38
  • 58
Atum
  • 1,211
  • 1
  • 12
  • 14
16

Note that this answer uses ehcache, which is one of supported Spring Boot cache managers, and arguably one of the most popular.

First you need to add to pom.xml:

<!-- Spring Framework Caching Support -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

In src/main/resources/ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
    <cache name="forecast" 
           maxElementsInMemory="1000" 
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU" />
</ehcache>
Hendy Irawan
  • 20,498
  • 11
  • 103
  • 114
Steve
  • 9,270
  • 5
  • 47
  • 61
  • 1
    Spring boot doesn't have *xml – nole Jan 15 '15 at 16:37
  • 8
    Oh yes there is! :) This is the default location for the EHCache configuration. Other caching libraries will presumably expect different locations. – Steve Jan 15 '15 at 16:39
15

From the reference documentation

Directly through your cache provider. The cache abstraction is… well, an abstraction not a cache implementation. The solution you are using might support various data policies and different topologies which other solutions do not (take for example the JDK ConcurrentHashMap) - exposing that in the cache abstraction would be useless simply because there would no backing support. Such functionality should be controlled directly through the backing cache, when configuring it or through its native API.

Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
  • 1
    Thank you. Finally I have added this in my application.yml: spring.resources.cache-period – nole Jan 15 '15 at 16:58
  • 3
    Sorry, I don't see the link with your example. Sounds like totally unrelated to me. That property is to configure the cache period of the web resources. – Stephane Nicoll Jan 16 '15 at 09:29
10

You cannot specify expiry time with @cacheable notation, since @cacheable does not provide any such configurable option.

However different caching vendors providing spring caching have provided this feature through their own configurations. For example NCache / TayzGrid allows you to create different cache regions with configurable expiration time.

If you have implemented your own cache, you will need to define a way to specify expiration in you cache provider and will also need to incorporate expiration logic in your solution.

Sameer Shah
  • 1,073
  • 7
  • 12
9

I use caffeine-caching, with this configuration for a 60 minute expiration:

spring.cache.cache-names=forecast
spring.cache.caffeine.spec=expireAfterWrite=60m
slartidan
  • 20,403
  • 15
  • 83
  • 131
  • If I use caffeine cache.how to fill `hibernate.cache.region.factory_class` in `spring.properties` – 袁文涛 Nov 08 '21 at 10:07
  • For others finding this answer, note that more information for these settings is in the [Spring Boot Documentation](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#io.caching.provider.caffeine). – Garret Wilson Aug 31 '23 at 17:03
4

You can achieve this kind of eviction strategy by making use of @Scheduled annotation. It is possible to schedule with a fixedRate or even with a cron expression.

@Autowired
CacheManager cacheManager;

public void evictAllCaches() {
        cacheManager.getCacheNames().stream()
          .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
}

@Scheduled(fixedRate = 6000)
public void evictAllcachesAtIntervals() {
        evictAllCaches();
}
talhature
  • 2,246
  • 1
  • 14
  • 28
  • 1
    This should be considered as a workaround as this clears the whole cache (contrary to the notion of expiration which is different for each cached element). – Julien Kronegg Jun 14 '22 at 15:03
  • @JulienKronegg you can create such schedules for each cache separately. I agree that it muat be not the most convenient way though. – havryliuk Feb 22 '23 at 08:37
2

Found this Spring cache: Set expiry time to a cache entry.

It uses the spring-boot-starter-cache dependency and works as expected . You can configure the expiry time for cached objects as well as the max number of cached values.

Amritansh
  • 172
  • 2
  • 6
1

If you are using Caffeine than you can add the following line in your application.properties file:

spring.cache.caffeine.spec=expireAfterAccess=300s
Bu Saeed
  • 1,173
  • 1
  • 16
  • 27