Reputation: 51
My application is on Spring boot 1.5.1
I have looked up all common problems related to caching not working in spring boot (calling a cacheable method from the same class, etc) and I still can't seem to pinpoint why my method is not cacheing. I am just trying to use the simple cache built into Spring (ie the concurrent hashmap).
Setup: in pom.xml I added this
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
My configuration class is the following:
@SpringBootApplication
@Configuration
@EnableCaching
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I have a controller class that has the following method to get a list of versions.
@RequestMapping(value = "/getVersionList", method = RequestMethod.GET)
public JSONObject getVersionList() {
JSONObject retJSON = new JSONObject();
List<String> versions = fetchVersionService.getVersionList();
retJSON.put("versions", versions);
return retJSON;
}
And the FetchVersionService class where I have the cacheable method to cache this versions list
@Cacheable("versions")
public List<String> getVersionList() {
System.out.println("If there is something in the cache, it should not hit here.");
return randomService.getVersions(); //another service class that gets versions from a remote location, which takes a long time
}
Whenever I make multiple GET calls to this function, it always goes inside the function even though I only expect to it execute the function once. For some reason it isn't cacheing the results. Any ideas where I went wrong with my setup? Thanks a lot.
Upvotes: 5
Views: 15752
Reputation: 4829
Below is an End to end working code to show case Caching implementation using SpringBoot.
@Cacheable("movies")
public List<String> getMoviesList() {
//logic to fetch movies using API call over webClient
return moviesList;
}
Now this code makes the response of getMoviesList cacheable due to annotation @Cacheable("movies")
However this is not enough, as it needs bean of CacheManager
as well.
In SpringBoot this is simplified, so all you need is @EnableCaching
This annotation can go in your main class with @SpringBootApplication
as shown below
@SpringBootApplication
@ConfigurationPropertiesScan
@EnableCaching
public class MoviesApplication {
public static void main(final String[] args) {
SpringApplication.run(MoviesApplication.class, args);
}
}
Now depending on your business workflow, you can decide the cache eviction policy.
@CacheEvict(value = "movies", allEntries = true)
@Scheduled(fixedDelay = 12, timeUnit = TimeUnit.HOURS)
public void evictMoviesFromCache() {
// Nothing to do. Annotations cover functionality
log.info("Evicting Movies from cache.");
}
Above code evicts the code at scheduled interval of 12 hrs.
Alternatively, you could evict it manually, as shown below.
@Component
public class CacheManagerService {
@CacheEvict("movies")
public void evictMoviesFromCache(final String networkRef) {
// nothing to add as this method is to evict the cache
}
}
And Autowire CacheManagerService in your code and invoke the method explicitly. for e.g.
@Service
@RequiredArgsConstructor
@Slf4j
public class MoviesCacheManager {
private final CacheManagerService cacheManagerService;
private final MoviesClient moviesClient;
public List<Location> refreshMovies() {
cacheManagerService.evictMoviesFromCache();
var movies = moviesClient.getMovies().collectList().block();
return Optional.ofNullable(movies).orElse(emptyList());
}
}
Reference: https://www.baeldung.com/spring-cache-tutorial
Upvotes: 2
Reputation: 188
In the comments under this question @irfanhasan mentions that they had imported the wrong package but there was no certain response. I faced the same problem. I tried to use @Cachable annotation but it wasn't work. I found that it was imported as:
import springfox.documentation.annotations.Cacheable
Instead of:
import org.springframework.cache.annotation.Cacheable;
Look carefully for your IDE imports.
Upvotes: 13
Reputation: 146
In the comments under this question, @irfanhasan mentions that they had imported the wrong package and @xetra11 replied asking which package was wrong which there was no reply to. I am not @irfanhasan but it might have been the following mixup: "You can also use the standard JSR-107 (JCache) annotations (such as @CacheResult) transparently. However, we strongly advise you to not mix and match the Spring Cache and JCache annotations."
Upvotes: 1