Java Spring Boot - How to cache data in your application
In this article, a demonstration on how to cache data in you Spring boot application will be shown. We will utilize the Cacheable annotation, and show how we can set it up in our application. In the last part, we will also show how we can flush the cache, using a schedule and clean out cached data that we want to be updated.
CacheConfig
We will start by setting up our cache configuration class. This class will be initializing our cache. In the configuration package of your project, add a new class called CacheConfiguration.java, and add following code:
package com.demo.springapi; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Scheduled; @Configuration @EnableCaching public class CachingConfig { public static final String MY_CACHE_COLLECTION_KEY = "my-data"; @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager(MY_CACHE_COLLECTION_KEY); } }
This will set up a cache, and we will add a cache entity called my-data. Note that we could add multiple collection keys to the constructor, like:
@Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager(MY_CACHE_COLLECTION_KEY, MY_OTHER_CACHE_KEY, MY_THIRD_CACHE_KEY); }
RestController
In our controllers, we can now use the Cacheable annotations on our endpoints in order to utilize our cache.
package com.demo.springapi.endpoints; import com.demo.springapi.CachingConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MyDataController { private final MyService myService; protected MyDataController(@Autowired MyService myService) { this.myService = myService; } @Cacheable(CachingConfig.MY_CACHE_COLLECTION_KEY) @GetMapping("/my-data") public ResponseEntity<MyData> getMyData() { return ResponseEntity.ok(myService.getMyData()); } }
And when we now call the GET /my-data endpoint, we will now only call our service one time, and then the cache will be used instead.
Flush the cache
The life cycle of the cache that are using the Cacheable annotation, will live for the whole run time of the application. The problem here, is that the cache could grow quite a lot, and also we might want the data to be refreshed once in a while. There are techniques to be used, such as CacheEvict and CachePut etc directly on the endpoints (read more here). But I found myself using another solution that I found in the Spring community, which I think works wonders when it comes to data that we are not manipulating ourself, but that we know are changing in the background. A good example of this is when using a third party API, for example fetching currency rates 😉.
Scheduling
In order to solve this, we can set up a scheduled method, using the Scheduled annotation. And then we can provide a fixed rate that the function should be called at. Let's add some code to our *CacheConfig**.
First, add EnableScheduling annotation to the class.
@EnableScheduling public class CachingConfig {}
Then, create a new method called flushCache and add following annotations
@CacheEvict(allEntries = true, value = {MY_CACHE_COLLECTION_KEY}) @Scheduled(fixedDelay = 60 * 60 * 1000, initialDelay = 500) public void flushCache() { System.out.println("Flush Cache"); }
This function, will run every hour and clean all entries in our provied cache collections, using the CacheEvict annotation. Here, you can specify which collections you want to flush, and at what rate. You can of course create more schedule methods if you want another cadence of the flushing.
Summary
In this article we took a look at how we can cache data in our Spring boot application, using Cachable annotation. We also demonstrated how we can flush the cache of specific collections in our cache using a scheduler.
I hope you enjoyed this article, and that it could assist you in your caching 😃.
Have a great day!