How cache data for specific time Spring Boot Rest Template

Viewed 3497

I am trying to find a way to cache some data for some specific period of time.

I am aware of @Cachable annotation, however I didn't find any way to get cache purged after some specific period of time.

@GetMapping("/{lang}.{format}")
@Timed
public ResponseEntity<Object> getLocalizedMessages(@PathVariable String lang,
                                                   @PathVariable String format,
                                                   @RequestParam("buildTimestamp") long buildTimestamp) throws InvalidArgumentException {

    Map<String, Object> messages = this.localeMessageService.getMessagesForLocale(lang);
    if (FORMAT_JSON.equals(format)) {
        String jsonMessages = new PropertiesToJsonConverter().convertFromValuesAsObjectMap(messages);
        return new ResponseEntity<>(jsonMessages, HttpStatus.OK);
    }
    return new ResponseEntity<>(messages, HttpStatus.OK);
}

Here is my rest method, I need to cache data based on the unix time, a timestamp passed as an argument, so for instance if an hour has passed the cache should be invalidated.

1 Answers

The Spring cache abstraction does not provide a cache store. A CacheManager configuration is necessarry to set up the actual store.

Here is an implementation example using Guava that supports time based eviction:

Add the guava dependency

Maven:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0-jre</version>
</dependency>

Gradle:

 compile 'com.google.guava:guava:27.0-jre'

Add a class to configure the caching

import com.google.common.cache.CacheBuilder;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager() {
            @Override
            protected Cache createConcurrentMapCache(final String name) {
                return new ConcurrentMapCache(name, CacheBuilder.newBuilder()
                        // You can customize here the eviction time
                        .expireAfterWrite(1, TimeUnit.HOURS)
                        .build()
                        .asMap(),
                        false);
            }
        };
    }

    @Bean
    public KeyGenerator keyGenerator() {
        return new SimpleKeyGenerator();
    }
}

Finally, add the @Cacheable("CacheName") annotation to the method you want the results to be cached

Related